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
|
// Dynamic Copy node: adapt connectors when something connects
|
||||||
HandleCopyNodeConnected(c);
|
HandleCopyNodeConnected(c);
|
||||||
|
|
||||||
|
// Dynamic Take node: adapt connectors when a list connects
|
||||||
|
HandleTakeNodeConnected(c);
|
||||||
})
|
})
|
||||||
.WhenRemoved(c =>
|
.WhenRemoved(c =>
|
||||||
{
|
{
|
||||||
@@ -54,6 +57,9 @@ namespace Nodify.Calculator
|
|||||||
|
|
||||||
// Dynamic Copy node: reset on disconnect
|
// Dynamic Copy node: reset on disconnect
|
||||||
HandleCopyNodeDisconnected(c);
|
HandleCopyNodeDisconnected(c);
|
||||||
|
|
||||||
|
// Dynamic Take node: reset on disconnect
|
||||||
|
HandleTakeNodeDisconnected(c);
|
||||||
});
|
});
|
||||||
|
|
||||||
Operations.WhenAdded(x =>
|
Operations.WhenAdded(x =>
|
||||||
@@ -66,6 +72,15 @@ namespace Nodify.Calculator
|
|||||||
ci.Output.WhenRemoved(RemoveConnection);
|
ci.Output.WhenRemoved(RemoveConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (x is TakeOperationViewModel takeVm)
|
||||||
|
{
|
||||||
|
takeVm.DisconnectNthAction = () =>
|
||||||
|
{
|
||||||
|
if (takeVm.NthConnector != null)
|
||||||
|
DisconnectConnector(takeVm.NthConnector);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void RemoveConnection(ConnectorViewModel i)
|
void RemoveConnection(ConnectorViewModel i)
|
||||||
{
|
{
|
||||||
var c = Connections.Where(con => con.Input == i || con.Output == i).ToArray();
|
var c = Connections.Where(con => con.Input == i || con.Output == i).ToArray();
|
||||||
@@ -127,7 +142,8 @@ namespace Nodify.Calculator
|
|||||||
!source.IsConnected &&
|
!source.IsConnected &&
|
||||||
!target.IsConnected &&
|
!target.IsConnected &&
|
||||||
source.IsInput != target.IsInput &&
|
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)
|
private static bool AreDataTypesCompatible(string sourceType, string targetType)
|
||||||
{
|
{
|
||||||
@@ -137,6 +153,17 @@ namespace Nodify.Calculator
|
|||||||
return string.Equals(sourceType, targetType, System.StringComparison.OrdinalIgnoreCase);
|
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)
|
internal void OpenGetSetVariable(Point TargetLocation, string className)
|
||||||
{
|
{
|
||||||
OperationsMenu.OpenOnlyGetSetVariable(TargetLocation, className);
|
OperationsMenu.OpenOnlyGetSetVariable(TargetLocation, className);
|
||||||
@@ -371,6 +398,99 @@ namespace Nodify.Calculator
|
|||||||
copyOp.Output.Remove(o);
|
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);
|
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>
|
/// <summary>
|
||||||
/// Returns a color based on the C# data type.
|
/// Returns a color based on the C# data type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -533,6 +533,23 @@
|
|||||||
</nodify:Node>
|
</nodify:Node>
|
||||||
</DataTemplate>
|
</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}">
|
<DataTemplate DataType="{x:Type local:OperationViewModel}">
|
||||||
<nodify:Node Content="{Binding Title}"
|
<nodify:Node Content="{Binding Title}"
|
||||||
Input="{Binding Input}"
|
Input="{Binding Input}"
|
||||||
|
|||||||
@@ -83,8 +83,7 @@ namespace Nodify.Calculator
|
|||||||
sysOp = SystemOperations.TAKE,
|
sysOp = SystemOperations.TAKE,
|
||||||
IsFlowNode = false
|
IsFlowNode = false
|
||||||
};
|
};
|
||||||
takeNode.Input.Add("");
|
takeNode.Input.Add("List");
|
||||||
takeNode.Output.Add("");
|
|
||||||
|
|
||||||
var authNode = new OperationInfoViewModel()
|
var authNode = new OperationInfoViewModel()
|
||||||
{
|
{
|
||||||
@@ -322,6 +321,39 @@ namespace Nodify.Calculator
|
|||||||
return authOp;
|
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
|
var sysOp = new SystemOperationViewModel
|
||||||
{
|
{
|
||||||
Title = info.Title,
|
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