Skip to content

Commit 15ded24

Browse files
DYN-8302: Optimizing loading of icons and preview bubble. (#16285)
Co-authored-by: DimitarVen <dimitar.venkov@autodesk.com>
1 parent 39e17d8 commit 15ded24

3 files changed

Lines changed: 76 additions & 11 deletions

File tree

src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,14 @@ internal GeometryScalingViewModel GeoScalingViewModel
583583
}
584584
}
585585

586+
/// <summary>
587+
/// Ensures that a preview control is initialized only when it is
588+
/// absolutely needed. It lives here so that it can be shared by
589+
/// all node views for reduced overhead and better management.
590+
/// </summary>
591+
internal Wpf.Utilities.ActionDebouncer DelayNodePreviewControl
592+
= new Wpf.Utilities.ActionDebouncer(null);
593+
586594
#endregion
587595

588596
public WorkspaceViewModel(WorkspaceModel model, DynamoViewModel dynamoViewModel)
@@ -746,6 +754,9 @@ public override void Dispose()
746754
InCanvasSearchViewModel?.Dispose();
747755
NodeAutoCompleteSearchViewModel.LuceneUtility?.DisposeAll();
748756
NodeAutoCompleteSearchViewModel?.Dispose();
757+
758+
DelayNodePreviewControl?.Dispose();
759+
DelayNodePreviewControl = null;
749760
}
750761

751762
internal void ZoomInInternal()

src/DynamoCoreWpf/Views/Core/NodeView.xaml.cs

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ public partial class NodeView : IViewModelView<NodeViewModel>
4949
/// Old ZIndex of node. It's set, when mouse leaves node.
5050
/// </summary>
5151
private int oldZIndex;
52-
5352
private bool nodeWasClicked;
5453

5554
public NodeView TopControl
@@ -296,6 +295,9 @@ public Grid PresentationGrid
296295
#region constructors
297296
static NodeView()
298297
{
298+
//Set bitmap scaling mode to low quality for default node icon.
299+
RenderOptions.SetBitmapScalingMode(_defaultNodeIcon, BitmapScalingMode.LowQuality);
300+
299301
//Freeze the static resource to reduce memory overhead
300302
_frozenImageSource.Freeze();
301303
_transientImageSource.Freeze();
@@ -641,6 +643,8 @@ public NodeView()
641643
Source = _frozenImageSource
642644
};
643645

646+
RenderOptions.SetBitmapScalingMode(FrozenImage, BitmapScalingMode.LowQuality);
647+
644648
FrozenImage.SetBinding(Grid.VisibilityProperty, new Binding("IsFrozen")
645649
{
646650
Converter = _boolToVisibilityCollapsedConverter,
@@ -659,6 +663,8 @@ public NodeView()
659663
Source = _transientImageSource
660664
};
661665

666+
RenderOptions.SetBitmapScalingMode(TransientImage, BitmapScalingMode.LowQuality);
667+
662668
TransientImage.SetBinding(Grid.VisibilityProperty, new Binding("IsTransient")
663669
{
664670
Converter = _boolToVisibilityCollapsedConverter,
@@ -677,6 +683,8 @@ public NodeView()
677683
Source = _hiddenEyeImageSource
678684
};
679685

686+
RenderOptions.SetBitmapScalingMode(HiddenEyeImage, BitmapScalingMode.LowQuality);
687+
680688
HiddenEyeImage.SetBinding(Grid.VisibilityProperty, new Binding("IsVisible")
681689
{
682690
Converter = _inverseBooleanToVisibilityCollapsedConverter,
@@ -1031,6 +1039,7 @@ public NodeView()
10311039
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
10321040
TargetNullValue = null
10331041
});
1042+
RenderOptions.SetBitmapScalingMode(zoomStateImgOne, BitmapScalingMode.LowQuality);
10341043

10351044
zoomGlyphRowZero.Children.Add(zoomStateImgOne);
10361045

@@ -1062,6 +1071,7 @@ public NodeView()
10621071
Converter = _emptyToVisibilityCollapsedConverter,
10631072
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
10641073
});
1074+
RenderOptions.SetBitmapScalingMode(zoomStateImgTwo, BitmapScalingMode.LowQuality);
10651075

10661076
// Image in column 1
10671077
var zoomStateImgThree = new Image
@@ -1085,6 +1095,7 @@ public NodeView()
10851095
Converter = _emptyToVisibilityCollapsedConverter,
10861096
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
10871097
});
1098+
RenderOptions.SetBitmapScalingMode(zoomStateImgThree, BitmapScalingMode.LowQuality);
10881099

10891100
zoomGlyphRowOne.Children.Add(zoomStateImgTwo);
10901101
zoomGlyphRowOne.Children.Add(zoomStateImgThree);
@@ -1537,6 +1548,21 @@ private static Style GetCodeBlockPortItemControlStyle()
15371548

15381549
#endregion
15391550

1551+
private void DelayPreviewControlAction()
1552+
{
1553+
if (!IsMouseOver) return;
1554+
1555+
TryShowPreviewBubbles();
1556+
}
1557+
1558+
private void InitialTryShowPreviewBubble()
1559+
{
1560+
// Always set old ZIndex to the last value, even if mouse is not over the node.
1561+
oldZIndex = NodeViewModel.StaticZIndex;
1562+
1563+
viewModel.WorkspaceViewModel.DelayNodePreviewControl.Debounce(300, DelayPreviewControlAction);
1564+
}
1565+
15401566
private void OnNodeViewUnloaded(object sender, RoutedEventArgs e)
15411567
{
15421568
ViewModel.NodeLogic.DispatchedToUI -= NodeLogic_DispatchedToUI;
@@ -1787,7 +1813,14 @@ private void NodeModel_ConnectorAdded(Graph.Connectors.ConnectorModel obj)
17871813
// try to show the preview bubble without new mouse enter event.
17881814
if (IsMouseOver)
17891815
{
1790-
Dispatcher.BeginInvoke(new Action(TryShowPreviewBubbles), DispatcherPriority.Loaded);
1816+
if (DynCmd.IsTestMode)
1817+
{
1818+
Dispatcher.BeginInvoke(new Action(TryShowPreviewBubbles), DispatcherPriority.Loaded);
1819+
}
1820+
else
1821+
{
1822+
InitialTryShowPreviewBubble();
1823+
}
17911824
}
17921825
}
17931826

@@ -2089,16 +2122,20 @@ private void OnNodeViewMouseEnter(object sender, MouseEventArgs e)
20892122
// if the node is located under "Hide preview bubbles" menu item and the item is clicked,
20902123
// ViewModel.DynamoViewModel.ShowPreviewBubbles will be updated AFTER node mouse enter event occurs
20912124
// so, wait while ShowPreviewBubbles binding updates value
2092-
Dispatcher.BeginInvoke(new Action(TryShowPreviewBubbles), DispatcherPriority.Loaded);
2125+
if (DynCmd.IsTestMode)
2126+
{
2127+
Dispatcher.BeginInvoke(new Action(TryShowPreviewBubbles), DispatcherPriority.Loaded);
2128+
}
2129+
else
2130+
{
2131+
InitialTryShowPreviewBubble();
2132+
}
20932133
}
20942134

20952135
private void TryShowPreviewBubbles()
20962136
{
20972137
nodeWasClicked = false;
20982138

2099-
// Always set old ZIndex to the last value, even if mouse is not over the node.
2100-
oldZIndex = NodeViewModel.StaticZIndex;
2101-
21022139
// There is no need run further.
21032140
if (IsPreviewDisabled()) return;
21042141

@@ -2123,23 +2160,30 @@ private bool IsPreviewDisabled()
21232160
// Or the user is selecting nodes
21242161
// Or preview is disabled for this node
21252162
// Or preview shouldn't be shown for some nodes (e.g. number sliders, watch nodes etc.)
2126-
// Or node is frozen.
2127-
// Or node is transient state.
2163+
// Or node is frozen
2164+
// Or we are panning the view.
21282165
return !ViewModel.DynamoViewModel.ShowPreviewBubbles ||
21292166
ViewModel.WorkspaceViewModel.IsConnecting ||
21302167
ViewModel.WorkspaceViewModel.IsSelecting || !previewEnabled ||
2131-
!ViewModel.IsPreviewInsetVisible || ViewModel.IsFrozen || viewModel.IsTransient;
2168+
!ViewModel.IsPreviewInsetVisible || ViewModel.IsFrozen ||
2169+
ViewModel.WorkspaceViewModel.IsPanning;
21322170
}
21332171

21342172
private void OnNodeViewMouseLeave(object sender, MouseEventArgs e)
21352173
{
21362174
ViewModel.ZIndex = oldZIndex;
2175+
viewModel.WorkspaceViewModel.DelayNodePreviewControl.Cancel();
21372176

2138-
//Watch nodes doesn't have Preview so we should avoid to use any method/property in PreviewControl class due that Preview is created automatically
2177+
// The preview hasn't been instantiated yet, we should stop here
2178+
if (previewControl == null) return;
2179+
2180+
// Watch nodes doesn't have Preview so we should avoid to use any method/property in PreviewControl class due that Preview is created automatically
21392181
if (ViewModel.NodeModel != null && ViewModel.NodeModel is CoreNodeModels.Watch) return;
21402182

21412183
// If mouse in over node/preview control or preview control is pined, we can not hide preview control.
2142-
if (IsMouseOver || PreviewControl.IsMouseOver || PreviewControl.StaysOpen || IsMouseInsidePreview(e) ||
2184+
// check the field and not the property because that will trigger the instantiation
2185+
if (IsMouseOver || previewControl?.IsMouseOver == true ||
2186+
previewControl?.StaysOpen == true || IsMouseInsidePreview(e) ||
21432187
(Mouse.Captured is DragCanvas && IsMouseInsideNodeOrPreview(e.GetPosition(this)))) return;
21442188

21452189
// If it's expanded, then first condense it.

src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,11 @@ private void OnCanvasMouseDown(object sender, MouseButtonEventArgs e)
901901
GeoScalingPopup.IsOpen = false;
902902

903903
if(PortContextMenu.IsOpen) DestroyPortContextMenu();
904+
905+
if (!ViewModel.IsPanning && e.MiddleButton == MouseButtonState.Pressed)
906+
{
907+
ViewModel.RequestTogglePanMode();
908+
}
904909
}
905910

906911
/// <summary>
@@ -937,6 +942,11 @@ private void OnMouseRelease(object sender, MouseButtonEventArgs e)
937942
// (not node, note, not buttons from viewControlPanel such as zoom, pan and so on)
938943
ContextMenuPopup.IsOpen = true;
939944
}
945+
946+
if (ViewModel.IsPanning && e.MiddleButton == MouseButtonState.Released)
947+
{
948+
ViewModel.RequestTogglePanMode();
949+
}
940950
}
941951

942952
private void OnMouseMove(object sender, MouseEventArgs e)

0 commit comments

Comments
 (0)