Skip to content
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
16 changes: 16 additions & 0 deletions src/DynamoCore/Graph/Connectors/ConnectorModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Dynamo.Graph.Workspaces;
using Dynamo.Utilities;
using Newtonsoft.Json;
using System.Linq;

namespace Dynamo.Graph.Connectors
{
Expand Down Expand Up @@ -122,6 +123,21 @@ public override Guid GUID
}
}

/// <summary>
/// Returns a snapshot of pin top-left canvas coordinates for this connector.
/// </summary>
internal IEnumerable<(double X, double Y)> GetPinLocations()
{
if (ConnectorPinModels == null || ConnectorPinModels.Count == 0)
{
return Enumerable.Empty<(double X, double Y)>();
}

return ConnectorPinModels
.Select(pin => (pin.X, pin.Y))
.ToList();
}

#endregion

#region constructors
Expand Down
77 changes: 70 additions & 7 deletions src/DynamoCore/Models/DynamoModelCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public void ExecuteCommand(RecordableCommand command)

private PortModel[] activeStartPorts;
private PortModel firstStartPort;
private Dictionary<Guid, List<(double X, double Y)>> reconnectionPinLocationsByStartPortId;

protected virtual void OpenFileImpl(OpenFileCommand command)
{
Expand Down Expand Up @@ -373,6 +374,7 @@ private void BeginConnection(Guid nodeId, int portIndex, PortType portType)
{
bool isInPort = portType == PortType.Input;
activeStartPorts = null;
reconnectionPinLocationsByStartPortId = null;

if (CurrentWorkspace.GetModelInternal(nodeId) is not NodeModel node)
return;
Expand All @@ -384,12 +386,13 @@ private void BeginConnection(Guid nodeId, int portIndex, PortType portType)
// to somewhere else (we don't allow the grabbing of the start connector).
if (portModel.Connectors.Count > 0 && portModel.Connectors[0].Start != portModel)
{
activeStartPorts = new PortModel[] { portModel.Connectors[0].Start };
firstStartPort = portModel.Connectors[0].Start;
ConnectorModel connector = portModel.Connectors[0];
activeStartPorts = new PortModel[] { connector.Start };
firstStartPort = connector.Start;
RecordReconnectionPinLocations(connector.Start, connector);
// Disconnect the connector model from its start and end ports
// and remove it from the connectors collection. This will also
// remove the view model.
ConnectorModel connector = portModel.Connectors[0];
if (CurrentWorkspace.Connectors.Contains(connector))
{
var models = new List<ModelBase> { connector };
Expand All @@ -411,6 +414,8 @@ private void BeginConnection(Guid nodeId, int portIndex, PortType portType)

private void BeginDuplicateConnection(Guid nodeId, int portIndex, PortType portType)
{
reconnectionPinLocationsByStartPortId = null;

// If the port clicked is an output port, begin connection as per normal
if (portType == PortType.Output)
{
Expand Down Expand Up @@ -441,6 +446,7 @@ private void BeginShiftReconnections(Guid nodeId, int portIndex, PortType portTy
{
if (portType == PortType.Input) return; //only handle multiple connections when the port selected is an output port
if (!(CurrentWorkspace.GetModelInternal(nodeId) is NodeModel node)) return;
reconnectionPinLocationsByStartPortId = null;

PortModel selectedPort = node.OutPorts[portIndex];

Expand All @@ -462,6 +468,7 @@ private void BeginShiftReconnections(Guid nodeId, int portIndex, PortType portTy
{
ConnectorModel connector = selectedConnectors[i];
activeStartPorts[i] = connector.End;
RecordReconnectionPinLocations(connector.End, connector);
}
CurrentWorkspace.SaveAndDeleteModels(selectedConnectors.ToList<ModelBase>());
return;
Expand All @@ -481,11 +488,15 @@ private void EndConnection(Guid nodeId, int portIndex, PortType portType)

PortModel portModel = isInPort ? node.InPorts[portIndex] : node.OutPorts[portIndex];

var models = GetConnectorsToAddAndDelete(portModel, activeStartPorts[0]);
var models = GetConnectorsToAddAndDelete(
portModel,
activeStartPorts[0],
ConsumeReconnectionPinLocations(activeStartPorts[0]));

WorkspaceModel.RecordModelsForUndo(models, CurrentWorkspace.UndoRecorder);
activeStartPorts = null;
firstStartPort = null;
reconnectionPinLocationsByStartPortId = null;
}

private void EndShiftReconnections(Guid nodeId, int portIndex, PortType portType)
Expand All @@ -496,17 +507,24 @@ private void EndShiftReconnections(Guid nodeId, int portIndex, PortType portType
if (!(CurrentWorkspace.GetModelInternal(nodeId) is NodeModel node)) return;
PortModel selectedPort = node.OutPorts[portIndex];

var firstModel = GetConnectorsToAddAndDelete(selectedPort, activeStartPorts[0]);
var firstModel = GetConnectorsToAddAndDelete(
selectedPort,
activeStartPorts[0],
ConsumeReconnectionPinLocations(activeStartPorts[0]));
for (int i = 1; i < activeStartPorts.Count(); i++)
{
var models = GetConnectorsToAddAndDelete(selectedPort, activeStartPorts[i]);
var models = GetConnectorsToAddAndDelete(
selectedPort,
activeStartPorts[i],
ConsumeReconnectionPinLocations(activeStartPorts[i]));
foreach (var m in models)
{
firstModel.Add(m.Key, m.Value);
}
}
WorkspaceModel.RecordModelsForUndo(firstModel, CurrentWorkspace.UndoRecorder);
activeStartPorts = null;
reconnectionPinLocationsByStartPortId = null;
return;
}

Expand All @@ -528,11 +546,14 @@ private void CancelConnections()
CurrentWorkspace.DeleteSavedModels();
activeStartPorts = null;
firstStartPort = null;
reconnectionPinLocationsByStartPortId = null;
return;
}

private static Dictionary<ModelBase, UndoRedoRecorder.UserAction> GetConnectorsToAddAndDelete(
PortModel endPort, PortModel startPort)
PortModel endPort,
PortModel startPort,
IEnumerable<(double X, double Y)> pinLocations = null)
{
ConnectorModel connectorToRemove = null;

Expand Down Expand Up @@ -573,10 +594,52 @@ private void CancelConnections()
if (newConnectorModel != null)
{
models.Add(newConnectorModel, UndoRedoRecorder.UserAction.Creation);

if (pinLocations != null)
{
foreach (var pinLocation in pinLocations)
{
var connectorPinModel = new ConnectorPinModel(
pinLocation.X,
pinLocation.Y,
Guid.NewGuid(),
newConnectorModel.GUID);

newConnectorModel.AddPin(connectorPinModel);
models.Add(connectorPinModel, UndoRedoRecorder.UserAction.Creation);
}
}
}
return models;
}

private void RecordReconnectionPinLocations(PortModel activeStartPort, ConnectorModel connector)
{
if (activeStartPort == null || connector == null)
{
return;
}

reconnectionPinLocationsByStartPortId ??= new Dictionary<Guid, List<(double X, double Y)>>();
reconnectionPinLocationsByStartPortId[activeStartPort.GUID] = connector.GetPinLocations().ToList();
}

private IEnumerable<(double X, double Y)> ConsumeReconnectionPinLocations(PortModel activeStartPort)
{
if (activeStartPort == null || reconnectionPinLocationsByStartPortId == null)
{
return Array.Empty<(double X, double Y)>();
}

if (!reconnectionPinLocationsByStartPortId.TryGetValue(activeStartPort.GUID, out var pinLocations))
{
return Array.Empty<(double X, double Y)>();
}

reconnectionPinLocationsByStartPortId.Remove(activeStartPort.GUID);
return pinLocations;
}

private void DeleteModelImpl(DeleteModelCommand command)
{
RequestHideNodeAutoCompleteBar?.Invoke();
Expand Down
2 changes: 2 additions & 0 deletions src/DynamoCoreWpf/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1890,6 +1890,8 @@ Dynamo.ViewModels.ConnectorPinViewModel.IsHidden.get -> bool
Dynamo.ViewModels.ConnectorPinViewModel.IsHidden.set -> void
Dynamo.ViewModels.ConnectorPinViewModel.IsHoveredOver.get -> bool
Dynamo.ViewModels.ConnectorPinViewModel.IsHoveredOver.set -> void
Dynamo.ViewModels.ConnectorPinViewModel.IsInteractive.get -> bool
Dynamo.ViewModels.ConnectorPinViewModel.IsInteractive.set -> void
Dynamo.ViewModels.ConnectorPinViewModel.IsSelected.get -> bool
Dynamo.ViewModels.ConnectorPinViewModel.IsTemporarilyVisible.get -> bool
Dynamo.ViewModels.ConnectorPinViewModel.IsTemporarilyVisible.set -> void
Expand Down
18 changes: 17 additions & 1 deletion src/DynamoCoreWpf/ViewModels/Core/ConnectorPinViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using Dynamo.Configuration;
using Dynamo.Graph;
Expand Down Expand Up @@ -225,6 +225,22 @@ public bool IsTemporarilyVisible
}
}

private bool isInteractive;
/// <summary>
/// Gets or sets whether the pin is interactive (can be hovered over, clicked on, etc.) and updates the command state when this changes.
/// </summary>
[JsonIgnore]
public bool IsInteractive
{
get => isInteractive;
set
{
if (isInteractive == value) return;
isInteractive = value;
RaisePropertyChanged(nameof(IsInteractive));
}
}

private bool isInGroup;
/// <summary>
/// Gets or sets whether the pin is in a group and updates the command state when this changes.
Expand Down
Loading
Loading