Implemente code for the take node and added functionality to take the list or array
This commit is contained in:
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -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,
|
||||
|
||||
40
Examples/Nodify.Calculator/TakeOperationViewModel.cs
Normal file
40
Examples/Nodify.Calculator/TakeOperationViewModel.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user