Skip to content

Commit

Permalink
Position node autocomplete UI against respective input port (#11190)
Browse files Browse the repository at this point in the history
* add events to place node autocomplete popup

* cleanup

* try using NodeAutoCompleteSearchControl events

* fix subscribe event

* cleanup

* review comments

* rename member var

* temporarily hardcode width of autocomplete search bar

* set control Width explicitly in xaml

* review comments

* update comments
  • Loading branch information
aparajit-pratap authored Oct 20, 2020
1 parent 93b0360 commit a23cbe7
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/DynamoCore/Core/DynamoSelection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public void AddRange(IEnumerable<T> range)
{
foreach (var item in range)
{
Items.Add(item);
Add(item);
}

this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
Expand Down
8 changes: 5 additions & 3 deletions src/DynamoCore/Graph/Nodes/NodeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,14 @@ public abstract class NodeModel : ModelBase, IRenderPackageSource<NodeModel>, ID
private ObservableCollection<PortModel> inPorts = new ObservableCollection<PortModel>();
private ObservableCollection<PortModel> outPorts = new ObservableCollection<PortModel>();

private readonly Dictionary<int, Tuple<int, NodeModel>> inputNodes;
private readonly Dictionary<int, HashSet<Tuple<int, NodeModel>>> outputNodes;

#endregion

#region public members
internal const double HeaderHeight = 25;

private readonly Dictionary<int, Tuple<int, NodeModel>> inputNodes;
private readonly Dictionary<int, HashSet<Tuple<int, NodeModel>>> outputNodes;
#region public members

/// <summary>
/// The unique name that was created the node by
Expand Down
3 changes: 1 addition & 2 deletions src/DynamoCore/Graph/Nodes/PortModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,9 @@ public Point2D Center
get
{
double halfHeight = Height * 0.5;
const double headerHeight = 25;

double offset = Owner.GetPortVerticalOffset(this);
double y = Owner.Y + headerHeight + 5 + halfHeight + offset;
double y = Owner.Y + NodeModel.HeaderHeight + 5 + halfHeight + offset;

switch (PortType)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
xmlns:uicontrols="clr-namespace:Dynamo.UI.Controls"
xmlns:resx="clr-namespace:Dynamo.Properties;assembly=DynamoCore"
mc:Ignorable="d"
MinWidth="250"
MinWidth="256"
IsVisibleChanged="OnNodeAutoCompleteSearchControlVisibilityChanged">
<UserControl.Resources>
<ResourceDictionary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,16 @@ public NodeAutoCompleteSearchControl()
{
Application.Current.Deactivated += currentApplicationDeactivated;
}
Loaded += NodeAutoCompleteSearchControl_Loaded;
Unloaded += NodeAutoCompleteSearchControl_Unloaded;
}

private void NodeAutoCompleteSearchControl_Loaded(object sender, RoutedEventArgs e)
{
if (ViewModel != null && ViewModel.PortViewModel != null)
{
ViewModel.PortViewModel.PlaceNodeAutocompleteWindow(this, e);
}
}

private void NodeAutoCompleteSearchControl_Unloaded(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -124,7 +132,6 @@ private void OnNodeAutoCompleteSearchControlVisibilityChanged(object sender, Dep
Dispatcher.BeginInvoke(new Action(() =>
{
SearchTextBox.Focus();
//ViewModel.InitializeDefaultAutoCompleteCandidates();
ViewModel.PopulateAutoCompleteCandidates();
}), DispatcherPriority.Loaded);
}
Expand Down
44 changes: 40 additions & 4 deletions src/DynamoCoreWpf/ViewModels/Core/PortViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System;
using System.Windows;
using System.Windows.Controls.Primitives;
using Dynamo.Graph.Nodes;
using Dynamo.Models;
using Dynamo.UI.Commands;
using Dynamo.UI.Controls;
using Dynamo.Utilities;

namespace Dynamo.ViewModels
Expand All @@ -16,6 +18,7 @@ public partial class PortViewModel : ViewModelBase
private readonly NodeViewModel _node;
private DelegateCommand _useLevelsCommand;
private DelegateCommand _keepListStructureCommand;
private const double autocompleteUISpacing = 2.5;

/// <summary>
/// Port model.
Expand Down Expand Up @@ -226,6 +229,38 @@ public override void Dispose()
_node.WorkspaceViewModel.PropertyChanged -= Workspace_PropertyChanged;
}

/// <summary>
/// Places the node autocomplete window relative to the respective port
/// once the control is loaded and when its actual width is known.
/// The UI is first placed w.r.t to the X, Y position of the node (to which the port belongs),
/// then offset from that based on the port, the width of the UI itself and in some cases, the node width.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
internal void PlaceNodeAutocompleteWindow(object sender, EventArgs e)
{
var control = sender as NodeAutoCompleteSearchControl;
var popup = control.Parent as Popup;

double x;
if (PortModel.PortType == PortType.Input)
{
// Position node autocomplete UI offset left by its width from X position of node.
// Note: MinWidth property of the control is set to a constant value in the XAML
// for the ActualWidth to return a consistent value.
x = _node.X - (control.ActualWidth + autocompleteUISpacing);
}
else
{
// Position node autocomplete UI offset right by node width from X position of node.
x = _node.X + _node.NodeModel.Width + autocompleteUISpacing;
}
// Position UI down from the top of the node but offset down by the node header and against the respective port.
var y = _node.Y + NodeModel.HeaderHeight + PortModel.Index * PortModel.Height;

popup.PlacementRectangle = new Rect(x, y, 0, 0);
}

private void Workspace_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
Expand Down Expand Up @@ -367,10 +402,11 @@ private bool CanConnect(object parameter)
// Handler to invoke node Auto Complete
private void AutoComplete(object parameter)
{
DynamoViewModel dynamoViewModel = _node.DynamoViewModel;
var svm = dynamoViewModel.CurrentSpaceViewModel.NodeAutoCompleteSearchViewModel as NodeAutoCompleteSearchViewModel;
svm.PortViewModel = parameter as PortViewModel;
dynamoViewModel.CurrentSpaceViewModel.OnRequestNodeAutoCompleteSearch(ShowHideFlags.Show);
var wsViewModel = _node.WorkspaceViewModel;
var svm = wsViewModel.NodeAutoCompleteSearchViewModel as NodeAutoCompleteSearchViewModel;
svm.PortViewModel = this;

wsViewModel.OnRequestNodeAutoCompleteSearch(ShowHideFlags.Show);
}

private bool CanAutoComplete(object parameter)
Expand Down
4 changes: 2 additions & 2 deletions src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,8 @@ private void OnRequestShowInCanvasSearch(object param)

internal event Action<ShowHideFlags> RequestNodeAutoCompleteSearch;

internal void OnRequestNodeAutoCompleteSearch(object param)
internal void OnRequestNodeAutoCompleteSearch(ShowHideFlags flag)
{
var flag = (ShowHideFlags)param;
RequestNodeAutoCompleteSearch?.Invoke(flag);
}

Expand Down Expand Up @@ -1401,6 +1400,7 @@ private void RefreshViewOnSelectionChange(object sender, NotifyCollectionChanged
RaisePropertyChanged("AnyNodeVisible");
RaisePropertyChanged("SelectionArgumentLacing");
}

}

public class ViewModelEventArgs : EventArgs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Dynamo.Controls;
using Dynamo.Search.SearchElements;
using Dynamo.Wpf.ViewModels;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,7 @@ protected virtual void CreateAndConnectToPort(object parameter)
DynamoSelection.Instance.ClearSelection();
var inputNodes = initialNode.InputNodes.Values.Where(x => x != null).Select(y => y.Item2);

foreach (var inputNode in inputNodes)
{
DynamoSelection.Instance.Selection.AddUnique(inputNode);
}
DynamoSelection.Instance.Selection.AddRange(inputNodes);
}

protected virtual bool CanCreateAndConnectToPort(object parameter)
Expand Down
2 changes: 0 additions & 2 deletions src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,6 @@
StaysOpen="True"
AllowsTransparency="True"
IsOpen="False"
Placement="MousePoint"
HorizontalOffset="-290"
DataContext="{Binding NodeAutoCompleteSearchViewModel}">
<ui:NodeAutoCompleteSearchControl RequestShowNodeAutoCompleteSearch="ShowHideNodeAutoCompleteControl" />
</Popup>
Expand Down
3 changes: 2 additions & 1 deletion src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ private void removeViewModelsubscriptions(WorkspaceViewModel ViewModel)
ViewModel.Model.RequestNodeCentered -= vm_RequestNodeCentered;
ViewModel.Model.RequestNodeCentered -= vm_RequestNodeCentered;
ViewModel.Model.CurrentOffsetChanged -= vm_CurrentOffsetChanged;
ViewModel.RequestNodeAutoCompleteSearch -= ShowHideNodeAutoCompleteControl;
}

void OnWorkspaceViewUnloaded(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -364,7 +365,7 @@ void OnWorkspaceViewDataContextChanged(object sender, DependencyPropertyChangedE
oldViewModel.RequestAddViewToOuterCanvas -= vm_RequestAddViewToOuterCanvas;
oldViewModel.WorkspacePropertyEditRequested -= VmOnWorkspacePropertyEditRequested;
oldViewModel.RequestSelectionBoxUpdate -= VmOnRequestSelectionBoxUpdate;
this.removeViewModelsubscriptions(oldViewModel);
removeViewModelsubscriptions(oldViewModel);
}

if (ViewModel != null)
Expand Down

0 comments on commit a23cbe7

Please sign in to comment.