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

DYN-4344 hotkey to unpin all node previews #15117

2 changes: 1 addition & 1 deletion src/AssemblySharedInfoGenerator/AssemblySharedInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// associated with an assembly.
[assembly: AssemblyCompany("Autodesk, Inc")]
[assembly: AssemblyProduct("Dynamo")]
[assembly: AssemblyCopyright("Copyright © Autodesk, Inc 2024")]
[assembly: AssemblyCopyright("Copyright © Autodesk, Inc 2024")]
QilongTang marked this conversation as resolved.
Show resolved Hide resolved
[assembly: AssemblyTrademark("")]

//In order to begin building localizable applications, set
Expand Down
17 changes: 16 additions & 1 deletion src/DynamoCoreWpf/Commands/WorkspaceCommands.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using Dynamo.Graph.Nodes;
using Dynamo.Graph.Workspaces;
using Dynamo.Selection;
Expand Down Expand Up @@ -30,6 +30,7 @@ public partial class WorkspaceViewModel
private DelegateCommand hideAllPopupCommand;
private DelegateCommand showAllWiresCommand;
private DelegateCommand hideAllWiresCommand;
private DelegateCommand unpinAllPreviewBubblesCommand;

#endregion

Expand Down Expand Up @@ -275,6 +276,20 @@ public DelegateCommand HideAllWiresCommand
return hideAllWiresCommand;
}
}

/// <summary>
/// View Command to hide all currently pinned preview bubbles within the workspace
/// </summary>
[JsonIgnore]
public DelegateCommand UnpinAllPreviewBubblesCommand
{
get
{
if (unpinAllPreviewBubblesCommand == null)
unpinAllPreviewBubblesCommand = new DelegateCommand(UnpinAllPreviewBubbles, CanUnpinAllPreviewBubbles);
return unpinAllPreviewBubblesCommand;
}
}
#endregion

#region Properties for Command Data Binding
Expand Down
9 changes: 9 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,10 @@ Don't worry, you'll have the option to save your work.</value>
<data name="DynamoViewEditMenuSelectAll" xml:space="preserve">
<value>_Select All</value>
<comment>Edit menu | Select all nodes</comment>
</data>
<data name="DynamoViewEditMenuUnpinAllPreviewBubbles" xml:space="preserve">
<value>_Unpin All Preview Bubbles</value>
<comment>Edit menu | Unpin preview bubbles</comment>
</data>
<data name="DynamoViewEditMenuSelectNeighbours" xml:space="preserve">
<value>_Select Neighbors</value>
Expand Down
4 changes: 4 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,10 @@
<data name="DynamoViewEditMenuSelectAll" xml:space="preserve">
<value>_Select All</value>
<comment>Edit menu | Select all nodes</comment>
</data>
<data name="DynamoViewEditMenuUnpinAllPreviewBubbles" xml:space="preserve">
<value>_Unpin All Preview Bubbles</value>
<comment>Edit menu | Unpin preview bubbles</comment>
</data>
<data name="DynamoViewEditMenuUndo" xml:space="preserve">
<value>_Undo</value>
Expand Down
7 changes: 7 additions & 0 deletions src/DynamoCoreWpf/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2024,6 +2024,9 @@ Dynamo.ViewModels.DynamoViewModel.ScaleFactorLog.set -> void
Dynamo.ViewModels.DynamoViewModel.SelectAll(object parameter) -> void
Dynamo.ViewModels.DynamoViewModel.SelectAllCommand.get -> Dynamo.UI.Commands.DelegateCommand
Dynamo.ViewModels.DynamoViewModel.SelectAllCommand.set -> void
Dynamo.ViewModels.DynamoViewModel.UnpinAllPreviewBubbles(object parameter) -> void
Dynamo.ViewModels.DynamoViewModel.UnpinAllPreviewBubblesCommand.get -> Dynamo.UI.Commands.DelegateCommand
Dynamo.ViewModels.DynamoViewModel.UnpinAllPreviewBubblesCommand.set -> void
Dynamo.ViewModels.DynamoViewModel.SelectNeighbors(object parameters) -> void
Dynamo.ViewModels.DynamoViewModel.SelectNeighborsCommand.get -> Dynamo.UI.Commands.DelegateCommand
Dynamo.ViewModels.DynamoViewModel.SelectNeighborsCommand.set -> void
Expand Down Expand Up @@ -3038,6 +3041,7 @@ Dynamo.ViewModels.WorkspaceViewModel.SetZoomCommand.get -> Dynamo.UI.Commands.De
Dynamo.ViewModels.WorkspaceViewModel.ShowAllWiresCommand.get -> Dynamo.UI.Commands.DelegateCommand
Dynamo.ViewModels.WorkspaceViewModel.ShowHideAllGeometryPreviewCommand.get -> Dynamo.UI.Commands.DelegateCommand
Dynamo.ViewModels.WorkspaceViewModel.ShowInCanvasSearchCommand.get -> Dynamo.UI.Commands.DelegateCommand
Dynamo.ViewModels.WorkspaceViewModel.UnpinAllPreviewBubblesTriggered -> Dynamo.ViewModels.ViewEventHandler
Dynamo.ViewModels.WorkspaceViewModel.Watch3DViewModels.get -> System.Collections.ObjectModel.ObservableCollection<Dynamo.ViewModels.Watch3DFullscreenViewModel>
Dynamo.ViewModels.WorkspaceViewModel.Watch3DViewModels.set -> void
Dynamo.ViewModels.WorkspaceViewModel.WorkspaceElements.get -> System.Windows.Data.CompositeCollection
Expand All @@ -3051,6 +3055,7 @@ Dynamo.ViewModels.WorkspaceViewModel.Zoom.get -> double
Dynamo.ViewModels.WorkspaceViewModel.Zoom.set -> void
Dynamo.ViewModels.WorkspaceViewModel.ZoomChanged -> Dynamo.ViewModels.WorkspaceViewModel.ZoomEventHandler
Dynamo.ViewModels.WorkspaceViewModel.ZoomEventHandler
Dynamo.ViewModels.WorkspaceViewModel.UnpinAllPreviewBubblesCommand.get -> Dynamo.UI.Commands.DelegateCommand
Dynamo.Views.GeometryScalingPopup
Dynamo.Views.GeometryScalingPopup.GeometryScalingPopup(Dynamo.ViewModels.DynamoViewModel dynViewModel) -> void
Dynamo.Views.GeometryScalingPopup.InitializeComponent() -> void
Expand All @@ -3075,6 +3080,7 @@ Dynamo.Views.WorkspaceView.Dispose() -> void
Dynamo.Views.WorkspaceView.HideAllPopUp(object sender) -> void
Dynamo.Views.WorkspaceView.InitializeComponent() -> void
Dynamo.Views.WorkspaceView.ViewModel.get -> Dynamo.ViewModels.WorkspaceViewModel
Dynamo.Views.WorkspaceView.vm_UnpinAllPreviewBubblesTriggered(object sender, System.EventArgs e) -> void
Dynamo.Views.WorkspaceView.WorkspacePropertyEditClick(object sender, System.Windows.RoutedEventArgs routedEventArgs) -> void
Dynamo.Views.WorkspaceView.WorkspaceView() -> void
Dynamo.Wpf.AssemblyNodeViewCustomizations
Expand Down Expand Up @@ -4520,6 +4526,7 @@ static Dynamo.Wpf.Properties.Resources.DynamoViewFileMenuOpenTemplate.get -> str
static Dynamo.Wpf.Properties.Resources.DynamoViewFileMenuRecentFiles.get -> string
static Dynamo.Wpf.Properties.Resources.DynamoViewFileMenuSave.get -> string
static Dynamo.Wpf.Properties.Resources.DynamoViewFileMenuSaveAs.get -> string
static Dynamo.Wpf.Properties.Resources.DynamoViewEditMenuUnpinAllPreviewBubbles.get -> string
static Dynamo.Wpf.Properties.Resources.DynamoViewHelpDictionary.get -> string
static Dynamo.Wpf.Properties.Resources.DynamoViewHelpMenu.get -> string
static Dynamo.Wpf.Properties.Resources.DynamoViewHelpMenuDisplayStartPage.get -> string
Expand Down
10 changes: 10 additions & 0 deletions src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2920,6 +2920,16 @@ internal bool CanSelectAll(object parameter)
return this.CurrentSpaceViewModel.CanSelectAll(null);
}

public void UnpinAllPreviewBubbles(object parameter)
{
this.CurrentSpaceViewModel.UnpinAllPreviewBubbles(null);
}

internal bool CanUnpinAllPreviewBubbles(object parameter)
{
return this.CurrentSpaceViewModel.CanUnpinAllPreviewBubbles(null);
}

public void MakeNewHomeWorkspace(object parameter)
{
if (ClearHomeWorkspaceInternal())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ private void InitializeDelegateCommands()
NodeFromSelectionCommand = new DelegateCommand(CreateNodeFromSelection, CanCreateNodeFromSelection);
OpenDocumentationLinkCommand = new DelegateCommand(OpenDocumentationLink);
ShowNodeDocumentationCommand = new DelegateCommand(ShowNodeDocumentation, CanShowNodeDocumentation);
UnpinAllPreviewBubblesCommand = new DelegateCommand(UnpinAllPreviewBubbles, CanUnpinAllPreviewBubbles);
}
public DelegateCommand OpenFromJsonIfSavedCommand { get; set; }
public DelegateCommand OpenFromJsonCommand { get; set; }
Expand Down Expand Up @@ -175,6 +176,6 @@ private void InitializeDelegateCommands()
public DelegateCommand NodeFromSelectionCommand { get; set; }
public DelegateCommand OpenDocumentationLinkCommand { get; set; }
public DelegateCommand ShowNodeDocumentationCommand { get; set; }

public DelegateCommand UnpinAllPreviewBubblesCommand { get; set; }
}
}
17 changes: 17 additions & 0 deletions src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1721,6 +1721,23 @@ private void ShowHideAllWires(List<NodeModel> nodeModels, bool isHidden)
}
}

public event ViewEventHandler UnpinAllPreviewBubblesTriggered;
/// <summary>
/// Triggers unpinning of all preview bubbles in the workspace
/// </summary>
/// <param name="o"></param>
internal void UnpinAllPreviewBubbles(object o)
{
RaisePropertyChanged("UnpinAllPreviewBubbles");

UnpinAllPreviewBubblesTriggered?.Invoke(this, EventArgs.Empty);
}

internal bool CanUnpinAllPreviewBubbles(object o)
{
return true;
}

/// <summary>
/// Collapse a set of nodes and notes currently selected in workspace
/// </summary>
Expand Down
8 changes: 7 additions & 1 deletion src/DynamoCoreWpf/Views/Core/DynamoView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@
<KeyBinding Key="A"
Modifiers="Control"
Command="{Binding Path=DataContext.SelectAllCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DynamoView}}}" />

<KeyBinding Key="K"
Modifiers="Control"
Command="{Binding Path=DataContext.UnpinAllPreviewBubblesCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DynamoView}}}" />
<KeyBinding Key="D"
Modifiers="Control"
Command="{Binding Path=DataContext.NodeFromSelectionCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DynamoView}}}" />
Expand Down Expand Up @@ -448,6 +450,10 @@
Command="{Binding SelectAllCommand}"
Name="selectAll"
InputGestureText="Ctrl + A" />
<MenuItem Header="{x:Static p:Resources.DynamoViewEditMenuUnpinAllPreviewBubbles}"
Command="{Binding UnpinAllPreviewBubblesCommand}"
Name="unpinPB"
InputGestureText="Ctrl + K"/>
<MenuItem Header="{x:Static p:Resources.DynamoViewEditMenuDeleteSelected}"
Command="{Binding DeleteCommand}"
Name="deleteSelected"
Expand Down
8 changes: 4 additions & 4 deletions src/DynamoCoreWpf/Views/Core/NodeView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ private void OnDataContextChanged(object sender, DependencyPropertyChangedEventA
{
// If this is the first time NodeView is bound to the NodeViewModel,
// cache the DataContext (i.e. NodeViewModel) locally and start
// referecing it from this point onwards. Note that this notification
// referencing it from this point onwards. Note that this notification
// can be sent as a result of DataContext becoming DisconnectedItem too,
// but ViewModel should not be updated in that case (hence the null-check).
//
Expand Down Expand Up @@ -224,7 +224,7 @@ private void OnNodeViewLoaded(object sender, RoutedEventArgs e)

private void NodeModel_ConnectorAdded(Graph.Connectors.ConnectorModel obj)
{
// If the mouse does not leave the node after the connnector is added,
// If the mouse does not leave the node after the connector is added,
// try to show the preview bubble without new mouse enter event.
if (IsMouseOver)
{
Expand Down Expand Up @@ -501,7 +501,7 @@ private void EditableNameBox_KeyDown(object sender, KeyEventArgs e)

#region Preview Control Related Event Handlers

private void OnNodeViewMouseEnter(object sender, MouseEventArgs e)
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
Expand Down Expand Up @@ -574,7 +574,7 @@ private void OnNodeViewMouseLeave(object sender, MouseEventArgs e)
/// This event fires right after preview's state has been changed.
/// This event is necessary, it handles some preview's manipulations,
/// that we can't handle in mouse enter/leave events.
/// E.g. When mouse leaves preview control, it should be first condesed, after that hidden.
/// E.g. When mouse leaves preview control, it should be first condensed, after that hidden.
/// </summary>
/// <param name="sender">PreviewControl</param>
/// <param name="e">Event arguments</param>
Expand Down
18 changes: 18 additions & 0 deletions src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ private void RemoveViewModelsubscriptions(WorkspaceViewModel ViewModel)
ViewModel.RequestAddViewToOuterCanvas -= vm_RequestAddViewToOuterCanvas;
ViewModel.WorkspacePropertyEditRequested -= VmOnWorkspacePropertyEditRequested;
ViewModel.RequestSelectionBoxUpdate -= VmOnRequestSelectionBoxUpdate;
ViewModel.UnpinAllPreviewBubblesTriggered -= vm_UnpinAllPreviewBubblesTriggered;

ViewModel.Model.RequestNodeCentered -= vm_RequestNodeCentered;
ViewModel.Model.CurrentOffsetChanged -= vm_CurrentOffsetChanged;
Expand Down Expand Up @@ -170,6 +171,7 @@ private void AttachViewModelsubscriptions(WorkspaceViewModel ViewModel)
ViewModel.RequestAddViewToOuterCanvas += vm_RequestAddViewToOuterCanvas;
ViewModel.WorkspacePropertyEditRequested += VmOnWorkspacePropertyEditRequested;
ViewModel.RequestSelectionBoxUpdate += VmOnRequestSelectionBoxUpdate;
ViewModel.UnpinAllPreviewBubblesTriggered += vm_UnpinAllPreviewBubblesTriggered;

ViewModel.Model.RequestNodeCentered += vm_RequestNodeCentered;
ViewModel.Model.CurrentOffsetChanged += vm_CurrentOffsetChanged;
Expand Down Expand Up @@ -783,6 +785,22 @@ private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
}
}

/// <summary>
/// Handles the event triggered when all preview bubbles in the workspace need to be unpinned
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void vm_UnpinAllPreviewBubblesTriggered(object sender, EventArgs e)
{
var nodesWithPinnedPreview = this.ChildrenOfType<NodeView>()
.Where(view => view.HasPreviewControl && view.PreviewControl.StaysOpen);

foreach (var node in nodesWithPinnedPreview)
{
node.PreviewControl.UnpinPreviewBubble();
}
}

private void OnCanvasMouseDown(object sender, MouseButtonEventArgs e)
{
ContextMenuPopup.IsOpen = false;
Expand Down
9 changes: 9 additions & 0 deletions src/DynamoCoreWpf/Views/Preview/PreviewControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ internal void HidePreviewBubble()
}
}

/// <summary>
/// Unpins and hides the preview bubbles
/// </summary>
internal void UnpinPreviewBubble()
{
StaysOpen = false;
this.HidePreviewBubble();
}

/// <summary>
/// It is possible for a run to complete while the preview display is
/// in transition. In these situations, we can store the MirrorData and
Expand Down
52 changes: 52 additions & 0 deletions test/DynamoCoreWpfTests/PreviewBubbleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,48 @@ public void PreviewBubble_ToggleShowPreviewBubbles()
Assert.IsTrue(nodeView.PreviewControl.IsHidden, "Preview bubble is not hidden");
}

[Test]
public void PreviewBubble_UnpinAllPreviewBubble()
{
Open(@"core\DetailedPreviewMargin_Test.dyn");

// List of GUIDs and corresponding NodeView instances
var guids = new List<string>
{
"1382aaf9-9432-4cf0-86ae-c586d311767e",
"81c94fd0-35a0-4680-8535-00aff41192d3",
"7828a9dd-88e6-49f4-9ed3-72e355f89bcc"
};
var nodeViews = guids.Select(guid => NodeViewWithGuid(guid)).ToList();

// Pin each preview bubble
foreach (var nodeView in nodeViews)
{
var previewBubble = nodeView.PreviewControl;
previewBubble.RaiseEvent(new RoutedEventArgs(FrameworkElement.LoadedEvent));
previewBubble.bubbleTools.RaiseEvent(new RoutedEventArgs(FrameworkElement.LoadedEvent));

// Simulate mouse enter events to trigger bubble visibility and pinning
RaiseMouseEnterOnNode(nodeView);
RaiseMouseEnterOnNode(previewBubble);
RaiseMouseEnterOnNode(previewBubble.bubbleTools);
RaiseLeftMouseClick(previewBubble.pinIconBorder);

// Assert the bubble is expanded and pinned
Assert.IsTrue(previewBubble.IsExpanded, "Expanded preview bubble should be shown");
Assert.IsTrue(previewBubble.StaysOpen, "Expanded preview bubble should be pinned");
}

// Execute command to unpin all preview bubbles
ViewModel.UnpinAllPreviewBubblesCommand.Execute(null);

// Assert all preview bubbles are unpinned
foreach (var nodeView in nodeViews)
{
Assert.IsTrue(!nodeView.PreviewControl.StaysOpen, "Expanded preview bubble should be unpinned");
}
}

[Test]
public void PreviewBubble_ShowExpandedPreviewOnPinIconHover()
{
Expand Down Expand Up @@ -923,6 +965,16 @@ private void RaiseMouseLeaveNode(IInputElement nv)
DispatcherUtil.DoEvents();
}

private void RaiseLeftMouseClick(IInputElement nv)
{
View.Dispatcher.Invoke(() =>
{
nv.RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) { RoutedEvent = Mouse.MouseDownEvent });
});

DispatcherUtil.DoEvents();
}

protected NodeModel GetNodeModel(string guid)
{
return Model.CurrentWorkspace.Nodes.First(n => n.GUID == Guid.Parse(guid));
Expand Down
Loading