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

WIP: Defer node view loading to speed up opening times (and possibly UX) of large graphs. #15784

Open
wants to merge 7 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
23 changes: 21 additions & 2 deletions src/DynamoCoreWpf/Commands/NoteCommands.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Dynamo.UI.Commands;
using Dynamo.Controls;
using Dynamo.UI.Commands;
using Dynamo.Utilities;
using Newtonsoft.Json;

namespace Dynamo.ViewModels
{
public partial class NoteViewModel
public partial class NoteViewModel: IWorkspaceElement
{
private DelegateCommand _selectCommand;
[JsonIgnore]
Expand Down Expand Up @@ -93,5 +95,22 @@ public DelegateCommand UnpinFromNodeCommand
return unpinFromNodeCommand;
}
}

/// <summary>
/// This signifies if the note should be rendered
/// </summary>
[JsonIgnore]
public bool IsVisibleInCanvas
{
get => isVisibleInCanvas;
set
{
isVisibleInCanvas = value;
RaisePropertyChanged(nameof(isVisibleInCanvas));
}
}
private bool isVisibleInCanvas = false;

public Rect2D Rect => Model.Rect;
}
}
52 changes: 52 additions & 0 deletions src/DynamoCoreWpf/Controls/DeferredContent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Windows;
using System.Windows.Controls;

namespace Dynamo.Controls
{
/// <summary>
/// https://stackoverflow.com/a/26543731
/// </summary>
public class DeferredContent : ContentPresenter
{
public DataTemplate DeferredContentTemplate
{
get { return (DataTemplate)GetValue(DeferredContentTemplateProperty); }
set { SetValue(DeferredContentTemplateProperty, value); }
}

public static readonly DependencyProperty DeferredContentTemplateProperty =
DependencyProperty.Register("DeferredContentTemplate",
typeof(DataTemplate), typeof(DeferredContent), null);

public DeferredContent()
{
IsVisibleChanged += DeferredContent_IsVisibleChanged;
}

private void DeferredContent_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (true.Equals(e.NewValue))
{
IsVisibleChanged -= DeferredContent_IsVisibleChanged;
Dispatcher.BeginInvoke(ShowDeferredContent);
}
}

public void ShowDeferredContent()
{
if (DeferredContentTemplate != null)
{
base.Content = DeferredContentTemplate.LoadContent();
RaiseDeferredContentLoaded();
}
}

private void RaiseDeferredContentLoaded()
{
DeferredContentLoaded?.Invoke(this, new RoutedEventArgs());
}

public event EventHandler<RoutedEventArgs> DeferredContentLoaded;
}
}
10 changes: 10 additions & 0 deletions src/DynamoCoreWpf/Controls/IWorkspaceElement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Dynamo.Utilities;

namespace Dynamo.Controls
{
internal interface IWorkspaceElement
{
bool IsVisibleInCanvas { get; set; }
Rect2D Rect { get; }
}
}
2 changes: 2 additions & 0 deletions src/DynamoCoreWpf/DynamoCoreWpf.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@
<DependentUpon>InstalledPackagesControl.xaml</DependentUpon>
</Compile>
<Compile Include="Commands\ConnectorPinCommands.cs" />
<Compile Include="Controls\IWorkspaceElement.cs" />
<Compile Include="Controls\NodeAutoCompleteSearchControl.xaml.cs">
<DependentUpon>NodeAutoCompleteSearchControl.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -455,6 +456,7 @@
<DependentUpon>AboutWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Views\CodeBlocks\CodeBlockEditor.cs" />
<Compile Include="Controls\DeferredContent.cs" />
<Compile Include="Views\Core\ConnectorAnchorView.xaml.cs">
<DependentUpon>ConnectorAnchorView.xaml</DependentUpon>
</Compile>
Expand Down
12 changes: 9 additions & 3 deletions src/DynamoCoreWpf/UI/Themes/Modern/DataTemplates.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@
<ResourceDictionary.MergedDictionaries>
<ui:SharedResourceDictionary Source="{x:Static ui:SharedDictionaryManager.DynamoConvertersDictionaryUri}" />
</ResourceDictionary.MergedDictionaries>

<DataTemplate DataType="{x:Type viewModels:NodeViewModel}">
<controls:NodeView></controls:NodeView>
<controls:DeferredContent
Content="{x:Null}">
<controls:DeferredContent.DeferredContentTemplate>
<DataTemplate>
<controls:NodeView />
</DataTemplate>
</controls:DeferredContent.DeferredContentTemplate>
</controls:DeferredContent>
</DataTemplate>

<DataTemplate DataType="{x:Type viewModels:NoteViewModel}">
Expand All @@ -27,4 +33,4 @@
<nodes:AnnotationView></nodes:AnnotationView>
</DataTemplate>

</ResourceDictionary>
</ResourceDictionary>
21 changes: 20 additions & 1 deletion src/DynamoCoreWpf/ViewModels/Core/AnnotationViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Windows.Input;
using System.Windows.Media;
using Dynamo.Configuration;
using Dynamo.Controls;
using Dynamo.Graph;
using Dynamo.Graph.Annotations;
using Dynamo.Graph.Nodes;
Expand All @@ -20,7 +21,7 @@

namespace Dynamo.ViewModels
{
public class AnnotationViewModel : ViewModelBase
public class AnnotationViewModel : ViewModelBase, IWorkspaceElement
{
private AnnotationModel annotationModel;
private IEnumerable<PortModel> originalInPorts;
Expand Down Expand Up @@ -371,6 +372,24 @@ public ObservableCollection<Configuration.StyleItem> GroupStyleList
RaisePropertyChanged(nameof(GroupStyleList));
}
}

/// <summary>
/// This signifies if the node should be rendered
/// </summary>
[JsonIgnore]
public bool IsVisibleInCanvas
{
get => isVisibleInCanvas;
set
{
isVisibleInCanvas = value;
RaisePropertyChanged(nameof(isVisibleInCanvas));
}
}
private bool isVisibleInCanvas = false;

public Rect2D Rect => AnnotationModel.Rect;

#endregion

#region Commands
Expand Down
21 changes: 20 additions & 1 deletion src/DynamoCoreWpf/ViewModels/Core/NodeViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using Dynamo.Configuration;
using Dynamo.Controls;
using Dynamo.Engine.CodeGeneration;
using Dynamo.Graph;
using Dynamo.Graph.Nodes;
Expand All @@ -20,6 +21,7 @@
using Dynamo.Logging;
using Dynamo.Models;
using Dynamo.Selection;
using Dynamo.Utilities;
using Dynamo.Wpf.ViewModels.Core;
using Newtonsoft.Json;
using Point = System.Windows.Point;
Expand All @@ -31,7 +33,7 @@ namespace Dynamo.ViewModels
/// Interaction logic for dynControl.xaml
/// </summary>

public partial class NodeViewModel : ViewModelBase
public partial class NodeViewModel : ViewModelBase, IWorkspaceElement
{
#region delegates
public delegate void SetToolTipDelegate(string message);
Expand Down Expand Up @@ -573,6 +575,23 @@ public bool NodeHoveringState
}
}

/// <summary>
/// This signifies if the node should be rendered
/// </summary>
[JsonIgnore]
public bool IsVisibleInCanvas
{
get => isVisibleInCanvas;
set
{
isVisibleInCanvas = value;
RaisePropertyChanged(nameof(isVisibleInCanvas));
}
}
private bool isVisibleInCanvas = false;

public Rect2D Rect => NodeModel.Rect;

private bool isNodeNewlyAdded;
private ImageSource imageSource;
private string imgGlyphOneSource;
Expand Down
57 changes: 55 additions & 2 deletions src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Windows.Data;
using System.Windows.Input;
using Dynamo.Configuration;
using Dynamo.Controls;
using Dynamo.Engine;
using Dynamo.Graph;
using Dynamo.Graph.Annotations;
Expand Down Expand Up @@ -533,6 +534,8 @@ internal GeometryScalingViewModel GeoScalingViewModel
}
}

private bool FinishedLoading = false;

#endregion

public WorkspaceViewModel(WorkspaceModel model, DynamoViewModel dynamoViewModel)
Expand Down Expand Up @@ -606,7 +609,9 @@ public WorkspaceViewModel(WorkspaceModel model, DynamoViewModel dynamoViewModel)
foreach (NoteModel note in Model.Notes) Model_NoteAdded(note);
foreach (AnnotationModel annotation in Model.Annotations) Model_AnnotationAdded(annotation);
foreach (ConnectorModel connector in Model.Connectors) Connectors_ConnectorAdded(connector);


FinishedLoading = true;

NodeAutoCompleteSearchViewModel = new NodeAutoCompleteSearchViewModel(DynamoViewModel)
{
Visible = true
Expand Down Expand Up @@ -823,6 +828,11 @@ private void Model_NoteAdded(NoteModel note)
{
var viewModel = new NoteViewModel(this, note);
Notes.Add(viewModel);

if (FinishedLoading)
{
viewModel.IsVisibleInCanvas = true;
}
}

private void Model_NoteRemoved(NoteModel note)
Expand All @@ -845,6 +855,11 @@ private void Model_AnnotationAdded(AnnotationModel annotation)
{
var viewModel = new AnnotationViewModel(this, annotation);
Annotations.Add(viewModel);

if (FinishedLoading)
{
viewModel.IsVisibleInCanvas = true;
}
}

private void Model_AnnotationRemoved(AnnotationModel annotation)
Expand Down Expand Up @@ -908,12 +923,21 @@ void Model_NodeAdded(NodeModel node)
var nodeViewModel = new NodeViewModel(this, node);
nodeViewModel.SnapInputEvent += nodeViewModel_SnapInputEvent;
nodeViewModel.NodeLogic.Modified += OnNodeModified;

lock (Nodes)
{
Nodes.Add(nodeViewModel);
}
if (nodeViewModel.ErrorBubble != null)
{
nodeViewModel.ErrorBubble.IsVisibleInCanvas = FinishedLoading;
Errors.Add(nodeViewModel.ErrorBubble);
}

if (FinishedLoading)
{
nodeViewModel.IsVisibleInCanvas = true;
}

PostNodeChangeActions();
}
Expand Down Expand Up @@ -1862,7 +1886,36 @@ internal IEnumerable<ViewModelBase> GetViewModelsInternal(IEnumerable<Guid> mode
return foundModels;
}


internal void UpdateWorkspaceElementVisibility(double visibleWidth, double visibleHeight)
{
var width = visibleWidth / Zoom;
var height = visibleHeight / Zoom;
var left = -X / Zoom;
var top = -Y / Zoom;

var visibleRect = new Rect2D(left, top, width, height);
var itemsToTest = Nodes.Cast<IWorkspaceElement>()
.Concat(Notes)
.Concat(Annotations);

foreach (var item in itemsToTest)
{
item.IsVisibleInCanvas = visibleRect.IntersectsWith(item.Rect);

if (item is NodeViewModel nvm && item.IsVisibleInCanvas && nvm.ErrorBubble != null)
{
nvm.ErrorBubble.IsVisibleInCanvas = true;
}
}

#if DEBUG
var total = Nodes.Count + Notes.Count + Annotations.Count;
var hidden = Nodes.Count(n => !n.IsVisibleInCanvas) +
Notes.Count(n => !n.IsVisibleInCanvas) +
Annotations.Count(a => !a.IsVisibleInCanvas);
Debug.WriteLine($"{hidden}/{total} workspace elements hidden");
#endif
}
}

public class ViewModelEventArgs : EventArgs
Expand Down
22 changes: 20 additions & 2 deletions src/DynamoCoreWpf/ViewModels/Preview/InfoBubbleViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using Dynamo.Controls;
using Dynamo.Logging;
using Dynamo.Utilities;
using Dynamo.Wpf.ViewModels.Core;

namespace Dynamo.ViewModels
Expand All @@ -26,7 +28,7 @@ public InfoBubbleEventArgs(Request request)

public delegate void InfoBubbleEventHandler(object sender, InfoBubbleEventArgs e);

public partial class InfoBubbleViewModel : ViewModelBase
public partial class InfoBubbleViewModel : ViewModelBase, IWorkspaceElement
{
public enum Style
{
Expand Down Expand Up @@ -444,7 +446,23 @@ public bool NodeWarningsIteratorVisible
/// and cannot have their Width (or Visibility) set manually.
/// </summary>
public bool NodeErrorsIteratorVisible => GetMessagesOfStyle(NodeMessages, Style.Error).Count > 1;


/// <summary>
/// This signifies if the node should be rendered
/// </summary>
public bool IsVisibleInCanvas
{
get => isVisibleInCanvas;
set
{
isVisibleInCanvas = value;
RaisePropertyChanged(nameof(isVisibleInCanvas));
}
}
private bool isVisibleInCanvas = false;

public Rect2D Rect => default;

#endregion

#region Event Handlers
Expand Down
3 changes: 3 additions & 0 deletions src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@
Value="{Binding Top}" />
<Setter Property="Panel.ZIndex"
Value="{Binding ZIndex}" />
<Setter
Property="Visibility"
Value="{Binding IsVisibleInCanvas, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay, FallbackValue=Visible}" />
</Style>
</ItemsControl.ItemContainerStyle>

Expand Down
Loading
Loading