Implemente code for the take node and added functionality to take the list or array

This commit is contained in:
Ankitkumar Satapara
2026-04-18 21:27:35 +05:30
parent 5b6af2a76b
commit c14a2a730d
5 changed files with 222 additions and 3 deletions

View File

@@ -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>" -> "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);
});
}
}
}

View File

@@ -120,6 +120,16 @@ namespace Nodify.Calculator
set => SetProperty(ref _isCopyConnector, value);
}
private bool _isTakeListConnector;
/// <summary>
/// When true, this connector belongs to a TAKE node and only accepts list/array types.
/// </summary>
public bool IsTakeListConnector
{
get => _isTakeListConnector;
set => SetProperty(ref _isTakeListConnector, value);
}
/// <summary>
/// Returns a color based on the C# data type.
/// </summary>

View File

@@ -533,6 +533,23 @@
</nodify:Node>
</DataTemplate>
<DataTemplate DataType="{x:Type local:TakeOperationViewModel}">
<nodify:Node Header="{Binding Title}"
Content="{Binding}"
Input="{Binding Input}"
Output="{Binding Output}">
<nodify:Node.ContentTemplate>
<DataTemplate DataType="{x:Type local:TakeOperationViewModel}">
<StackPanel Margin="4">
<CheckBox Content="Random"
IsChecked="{Binding IsRandom, UpdateSourceTrigger=PropertyChanged}"
Foreground="White" Margin="0 0 0 4" />
</StackPanel>
</DataTemplate>
</nodify:Node.ContentTemplate>
</nodify:Node>
</DataTemplate>
<DataTemplate DataType="{x:Type local:OperationViewModel}">
<nodify:Node Content="{Binding Title}"
Input="{Binding Input}"

View File

@@ -83,8 +83,7 @@ namespace Nodify.Calculator
sysOp = SystemOperations.TAKE,
IsFlowNode = false
};
takeNode.Input.Add("");
takeNode.Output.Add("");
takeNode.Input.Add("List");
var authNode = new OperationInfoViewModel()
{
@@ -322,6 +321,39 @@ namespace Nodify.Calculator
return authOp;
}
if (info.sysOp == SystemOperations.TAKE)
{
var takeOp = new TakeOperationViewModel
{
Title = info.Title,
SystemOperationType = SystemOperations.TAKE
};
// List input — accepts any shape but only list/array DataTypes
foreach (var item in input)
{
item.Shape = ConnectorShape.Circle;
item.ConnectorColor = Color.White;
item.IsCopyConnector = true;
item.IsTakeListConnector = true;
item.Title = "List";
takeOp.Input.Add(item);
}
// Nth index input (int type)
var nthConnector = new ConnectorViewModel
{
Title = "Nth",
Shape = ConnectorShape.Circle,
ConnectorColor = ConnectorViewModel.GetColorForType("int"),
DataType = "int"
};
takeOp.NthConnector = nthConnector;
takeOp.Input.Add(nthConnector);
return takeOp;
}
var sysOp = new SystemOperationViewModel
{
Title = info.Title,

View File

@@ -0,0 +1,40 @@
using System;
using System.Linq;
namespace Nodify.Calculator
{
public class TakeOperationViewModel : SystemOperationViewModel
{
private int _nthIndex;
public int NthIndex
{
get => _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();
}
}
}
/// <summary>
/// Reference to the Nth input connector so we can manage it.
/// </summary>
public ConnectorViewModel? NthConnector { get; set; }
/// <summary>
/// Callback set by the CalculatorViewModel to disconnect the Nth connector.
/// </summary>
public Action? DisconnectNthAction { get; set; }
}
}