Skip to content
11 changes: 11 additions & 0 deletions src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,14 @@ internal GeometryScalingViewModel GeoScalingViewModel
}
}

/// <summary>
/// Ensures that a preview control is initialized only when it is
/// absolutely needed. It lives here so that it can be shared by
/// all node views for reduced overhead and better management.
/// </summary>
internal Wpf.Utilities.ActionDebouncer DelayNodePreviewControl
= new Wpf.Utilities.ActionDebouncer(null);

#endregion

public WorkspaceViewModel(WorkspaceModel model, DynamoViewModel dynamoViewModel)
Expand Down Expand Up @@ -746,6 +754,9 @@ public override void Dispose()
InCanvasSearchViewModel?.Dispose();
NodeAutoCompleteSearchViewModel.LuceneUtility?.DisposeAll();
NodeAutoCompleteSearchViewModel?.Dispose();

DelayNodePreviewControl?.Dispose();
DelayNodePreviewControl = null;
}

internal void ZoomInInternal()
Expand Down
66 changes: 55 additions & 11 deletions src/DynamoCoreWpf/Views/Core/NodeView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ public partial class NodeView : IViewModelView<NodeViewModel>
/// Old ZIndex of node. It's set, when mouse leaves node.
/// </summary>
private int oldZIndex;

private bool nodeWasClicked;

public NodeView TopControl
Expand Down Expand Up @@ -296,6 +295,9 @@ public Grid PresentationGrid
#region constructors
static NodeView()
{
//Set bitmap scaling mode to low quality for default node icon.
RenderOptions.SetBitmapScalingMode(_defaultNodeIcon, BitmapScalingMode.LowQuality);

//Freeze the static resource to reduce memory overhead
_frozenImageSource.Freeze();
_transientImageSource.Freeze();
Expand Down Expand Up @@ -641,6 +643,8 @@ public NodeView()
Source = _frozenImageSource
};

RenderOptions.SetBitmapScalingMode(FrozenImage, BitmapScalingMode.LowQuality);

FrozenImage.SetBinding(Grid.VisibilityProperty, new Binding("IsFrozen")
{
Converter = _boolToVisibilityCollapsedConverter,
Expand All @@ -659,6 +663,8 @@ public NodeView()
Source = _transientImageSource
};

RenderOptions.SetBitmapScalingMode(TransientImage, BitmapScalingMode.LowQuality);

TransientImage.SetBinding(Grid.VisibilityProperty, new Binding("IsTransient")
{
Converter = _boolToVisibilityCollapsedConverter,
Expand All @@ -677,6 +683,8 @@ public NodeView()
Source = _hiddenEyeImageSource
};

RenderOptions.SetBitmapScalingMode(HiddenEyeImage, BitmapScalingMode.LowQuality);

HiddenEyeImage.SetBinding(Grid.VisibilityProperty, new Binding("IsVisible")
{
Converter = _inverseBooleanToVisibilityCollapsedConverter,
Expand Down Expand Up @@ -1031,6 +1039,7 @@ public NodeView()
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
TargetNullValue = null
});
RenderOptions.SetBitmapScalingMode(zoomStateImgOne, BitmapScalingMode.LowQuality);

zoomGlyphRowZero.Children.Add(zoomStateImgOne);

Expand Down Expand Up @@ -1062,6 +1071,7 @@ public NodeView()
Converter = _emptyToVisibilityCollapsedConverter,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
RenderOptions.SetBitmapScalingMode(zoomStateImgTwo, BitmapScalingMode.LowQuality);

// Image in column 1
var zoomStateImgThree = new Image
Expand All @@ -1085,6 +1095,7 @@ public NodeView()
Converter = _emptyToVisibilityCollapsedConverter,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
RenderOptions.SetBitmapScalingMode(zoomStateImgThree, BitmapScalingMode.LowQuality);

zoomGlyphRowOne.Children.Add(zoomStateImgTwo);
zoomGlyphRowOne.Children.Add(zoomStateImgThree);
Expand Down Expand Up @@ -1536,6 +1547,21 @@ private static Style GetCodeBlockPortItemControlStyle()

#endregion

private void DelayPreviewControlAction()
{
if (!IsMouseOver) return;

TryShowPreviewBubbles();
}

private void InitialTryShowPreviewBubble()
{
// Always set old ZIndex to the last value, even if mouse is not over the node.
oldZIndex = NodeViewModel.StaticZIndex;

viewModel.WorkspaceViewModel.DelayNodePreviewControl.Debounce(300, DelayPreviewControlAction);
}

private void OnNodeViewUnloaded(object sender, RoutedEventArgs e)
{
ViewModel.NodeLogic.DispatchedToUI -= NodeLogic_DispatchedToUI;
Expand Down Expand Up @@ -1763,7 +1789,14 @@ private void NodeModel_ConnectorAdded(Graph.Connectors.ConnectorModel obj)
// try to show the preview bubble without new mouse enter event.
if (IsMouseOver)
{
Dispatcher.BeginInvoke(new Action(TryShowPreviewBubbles), DispatcherPriority.Loaded);
if (DynCmd.IsTestMode)
{
Dispatcher.BeginInvoke(new Action(TryShowPreviewBubbles), DispatcherPriority.Loaded);
}
else
{
InitialTryShowPreviewBubble();
}
}
}

Expand Down Expand Up @@ -2065,16 +2098,20 @@ private void OnNodeViewMouseEnter(object sender, MouseEventArgs e)
// if the node is located under "Hide preview bubbles" menu item and the item is clicked,
// ViewModel.DynamoViewModel.ShowPreviewBubbles will be updated AFTER node mouse enter event occurs
// so, wait while ShowPreviewBubbles binding updates value
Dispatcher.BeginInvoke(new Action(TryShowPreviewBubbles), DispatcherPriority.Loaded);
if (DynCmd.IsTestMode)
{
Dispatcher.BeginInvoke(new Action(TryShowPreviewBubbles), DispatcherPriority.Loaded);
}
else
{
InitialTryShowPreviewBubble();
}
}

private void TryShowPreviewBubbles()
{
nodeWasClicked = false;

// Always set old ZIndex to the last value, even if mouse is not over the node.
oldZIndex = NodeViewModel.StaticZIndex;

// There is no need run further.
if (IsPreviewDisabled()) return;

Expand All @@ -2099,23 +2136,30 @@ private bool IsPreviewDisabled()
// Or the user is selecting nodes
// Or preview is disabled for this node
// Or preview shouldn't be shown for some nodes (e.g. number sliders, watch nodes etc.)
// Or node is frozen.
// Or node is transient state.
// Or node is frozen
// Or we are panning the view.
return !ViewModel.DynamoViewModel.ShowPreviewBubbles ||
ViewModel.WorkspaceViewModel.IsConnecting ||
ViewModel.WorkspaceViewModel.IsSelecting || !previewEnabled ||
!ViewModel.IsPreviewInsetVisible || ViewModel.IsFrozen || viewModel.IsTransient;
!ViewModel.IsPreviewInsetVisible || ViewModel.IsFrozen ||
ViewModel.WorkspaceViewModel.IsPanning;
}

private void OnNodeViewMouseLeave(object sender, MouseEventArgs e)
{
ViewModel.ZIndex = oldZIndex;
viewModel.WorkspaceViewModel.DelayNodePreviewControl.Cancel();

//Watch nodes doesn't have Preview so we should avoid to use any method/property in PreviewControl class due that Preview is created automatically
// The preview hasn't been instantiated yet, we should stop here
if (previewControl == null) return;

// Watch nodes doesn't have Preview so we should avoid to use any method/property in PreviewControl class due that Preview is created automatically
if (ViewModel.NodeModel != null && ViewModel.NodeModel is CoreNodeModels.Watch) return;

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

// If it's expanded, then first condense it.
Expand Down
10 changes: 10 additions & 0 deletions src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,11 @@ private void OnCanvasMouseDown(object sender, MouseButtonEventArgs e)
GeoScalingPopup.IsOpen = false;

if(PortContextMenu.IsOpen) DestroyPortContextMenu();

if (!ViewModel.IsPanning && e.MiddleButton == MouseButtonState.Pressed)
{
ViewModel.RequestTogglePanMode();
}
}

/// <summary>
Expand Down Expand Up @@ -937,6 +942,11 @@ private void OnMouseRelease(object sender, MouseButtonEventArgs e)
// (not node, note, not buttons from viewControlPanel such as zoom, pan and so on)
ContextMenuPopup.IsOpen = true;
}

if (ViewModel.IsPanning && e.MiddleButton == MouseButtonState.Released)
{
ViewModel.RequestTogglePanMode();
}
}

private void OnMouseMove(object sender, MouseEventArgs e)
Expand Down
Loading