From c14a2a730d90c3ffbafc52936c248c9a33a80fb4 Mon Sep 17 00:00:00 2001 From: Ankitkumar Satapara Date: Sat, 18 Apr 2026 21:27:35 +0530 Subject: [PATCH] Implemente code for the take node and added functionality to take the list or array --- .../Nodify.Calculator/CalculatorViewModel.cs | 122 +++++++++++++++++- .../Nodify.Calculator/ConnectorViewModel.cs | 10 ++ Examples/Nodify.Calculator/EditorView.xaml | 17 +++ .../Operations/OperationFactory.cs | 36 +++++- .../TakeOperationViewModel.cs | 40 ++++++ 5 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 Examples/Nodify.Calculator/TakeOperationViewModel.cs diff --git a/Examples/Nodify.Calculator/CalculatorViewModel.cs b/Examples/Nodify.Calculator/CalculatorViewModel.cs index c6b8dd6..99f9efa 100644 --- a/Examples/Nodify.Calculator/CalculatorViewModel.cs +++ b/Examples/Nodify.Calculator/CalculatorViewModel.cs @@ -31,6 +31,9 @@ namespace Nodify.Calculator // Dynamic Copy node: adapt connectors when something connects HandleCopyNodeConnected(c); + + // Dynamic Take node: adapt connectors when a list connects + HandleTakeNodeConnected(c); }) .WhenRemoved(c => { @@ -54,6 +57,9 @@ namespace Nodify.Calculator // Dynamic Copy node: reset on disconnect HandleCopyNodeDisconnected(c); + + // Dynamic Take node: reset on disconnect + HandleTakeNodeDisconnected(c); }); Operations.WhenAdded(x => @@ -66,6 +72,15 @@ namespace Nodify.Calculator ci.Output.WhenRemoved(RemoveConnection); } + if (x is TakeOperationViewModel takeVm) + { + takeVm.DisconnectNthAction = () => + { + if (takeVm.NthConnector != null) + DisconnectConnector(takeVm.NthConnector); + }; + } + void RemoveConnection(ConnectorViewModel i) { var c = Connections.Where(con => con.Input == i || con.Output == i).ToArray(); @@ -127,7 +142,8 @@ namespace Nodify.Calculator !source.IsConnected && !target.IsConnected && source.IsInput != target.IsInput && - AreDataTypesCompatible(source.DataType, target.DataType)); + AreDataTypesCompatible(source.DataType, target.DataType) && + !IsTakeListBlockedConnection(source, target)); private static bool AreDataTypesCompatible(string sourceType, string targetType) { @@ -137,6 +153,17 @@ namespace Nodify.Calculator return string.Equals(sourceType, targetType, System.StringComparison.OrdinalIgnoreCase); } + private static bool IsTakeListBlockedConnection(ConnectorViewModel source, ConnectorViewModel target) + { + // If one side is a TAKE list connector, the other must have a list/array DataType + var takeConn = source.IsTakeListConnector ? source : target.IsTakeListConnector ? target : null; + if (takeConn == null) return false; + + var otherConn = takeConn == source ? target : source; + var dt = (otherConn.DataType ?? "").ToLower(); + return !(dt.StartsWith("list<") || dt.EndsWith("[]")); + } + internal void OpenGetSetVariable(Point TargetLocation, string className) { OperationsMenu.OpenOnlyGetSetVariable(TargetLocation, className); @@ -371,6 +398,99 @@ namespace Nodify.Calculator copyOp.Output.Remove(o); }); } + + private void HandleTakeNodeConnected(ConnectionViewModel c) + { + // Find the TAKE node's list input (IsCopyConnector on input side) + ConnectorViewModel takeListInput = null; + ConnectorViewModel sourceConnector = null; + + if (c.Input.IsCopyConnector && c.Input.IsInput) + { + var op = c.Input.Operation; + if (op is TakeOperationViewModel) + { + takeListInput = c.Input; + sourceConnector = c.Output; + } + } + else if (c.Output.IsCopyConnector && c.Output.IsInput) + { + var op = c.Output.Operation; + if (op is TakeOperationViewModel) + { + takeListInput = c.Output; + sourceConnector = c.Input; + } + } + + if (takeListInput == null || sourceConnector == null) return; + + var takeOp = (TakeOperationViewModel)takeListInput.Operation; + + // Adapt the list input to match source shape/color + takeListInput.Shape = sourceConnector.Shape; + takeListInput.ConnectorColor = sourceConnector.RawColor; + takeListInput.DataType = sourceConnector.DataType; + + // Determine the element type from a list type (e.g. "list" -> "int") + var elementType = sourceConnector.DataType ?? ""; + if (elementType.StartsWith("list<") && elementType.EndsWith(">")) + { + elementType = elementType.Substring(5, elementType.Length - 6); + } + + var elementColor = ConnectorViewModel.GetColorForType(elementType); + + // Remove existing outputs + var toRemove = takeOp.Output.ToList(); + toRemove.ForEach(o => + { + DisconnectConnector(o); + takeOp.Output.Remove(o); + }); + + // Add single output for the element type + takeOp.Output.Add(new ConnectorViewModel + { + Title = "Element", + IsInput = false, + Shape = ConnectorShape.Circle, + ConnectorColor = elementColor, + DataType = elementType + }); + } + + private void HandleTakeNodeDisconnected(ConnectionViewModel c) + { + ConnectorViewModel takeListInput = null; + + if (c.Input.IsCopyConnector && c.Input.IsInput && c.Input.Operation is TakeOperationViewModel) + takeListInput = c.Input; + else if (c.Output.IsCopyConnector && c.Output.IsInput && c.Output.Operation is TakeOperationViewModel) + takeListInput = c.Output; + + if (takeListInput == null) return; + + var takeOp = (TakeOperationViewModel)takeListInput.Operation; + + // Check if input still has a connection + var stillConnected = Connections.Any(con => con.Input == takeListInput || con.Output == takeListInput); + if (stillConnected) return; + + // Reset list input to universal + takeListInput.Shape = ConnectorShape.Circle; + takeListInput.ConnectorColor = System.Drawing.Color.White; + takeListInput.DataType = string.Empty; + + // Remove all outputs + var toRemove = takeOp.Output.ToList(); + toRemove.ForEach(o => + { + DisconnectConnector(o); + takeOp.Output.Remove(o); + }); + } } } diff --git a/Examples/Nodify.Calculator/ConnectorViewModel.cs b/Examples/Nodify.Calculator/ConnectorViewModel.cs index 169c974..8855b0b 100644 --- a/Examples/Nodify.Calculator/ConnectorViewModel.cs +++ b/Examples/Nodify.Calculator/ConnectorViewModel.cs @@ -120,6 +120,16 @@ namespace Nodify.Calculator set => SetProperty(ref _isCopyConnector, value); } + private bool _isTakeListConnector; + /// + /// When true, this connector belongs to a TAKE node and only accepts list/array types. + /// + public bool IsTakeListConnector + { + get => _isTakeListConnector; + set => SetProperty(ref _isTakeListConnector, value); + } + /// /// Returns a color based on the C# data type. /// diff --git a/Examples/Nodify.Calculator/EditorView.xaml b/Examples/Nodify.Calculator/EditorView.xaml index 46f8f90..6ec3c7a 100644 --- a/Examples/Nodify.Calculator/EditorView.xaml +++ b/Examples/Nodify.Calculator/EditorView.xaml @@ -533,6 +533,23 @@ + + + + + + + + + + + + _nthIndex; + set => SetProperty(ref _nthIndex, value); + } + + private bool _isRandom; + public bool IsRandom + { + get => _isRandom; + set + { + if (SetProperty(ref _isRandom, value) && value) + { + NthIndex = 0; + // Disconnect the Nth connector via the callback + DisconnectNthAction?.Invoke(); + } + } + } + + /// + /// Reference to the Nth input connector so we can manage it. + /// + public ConnectorViewModel? NthConnector { get; set; } + + /// + /// Callback set by the CalculatorViewModel to disconnect the Nth connector. + /// + public Action? DisconnectNthAction { get; set; } + } +}