Implemented reading input from the textbox instead of connectors
This commit is contained in:
@@ -31,6 +31,19 @@ namespace Nodify.Calculator
|
|||||||
.Then(() => ValueObservers.ForEach(o => o.Value = value));
|
.Then(() => ValueObservers.ForEach(o => o.Value = value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string _userInput = string.Empty;
|
||||||
|
/// <summary>
|
||||||
|
/// Free-form text the user types directly into the connector's input textbox
|
||||||
|
/// (visible only when the connector is not connected). Used by handlers like
|
||||||
|
/// NEW_OBJECT to read non-numeric values (strings, bools, JSON snippets, ...)
|
||||||
|
/// that <see cref="Value"/> (a double) cannot represent.
|
||||||
|
/// </summary>
|
||||||
|
public string UserInput
|
||||||
|
{
|
||||||
|
get => _userInput;
|
||||||
|
set => SetProperty(ref _userInput, value);
|
||||||
|
}
|
||||||
|
|
||||||
private ConnectorShape _shape;
|
private ConnectorShape _shape;
|
||||||
public ConnectorShape Shape
|
public ConnectorShape Shape
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -273,7 +273,8 @@
|
|||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Text="{Binding Title}"
|
<TextBlock Text="{Binding Title}"
|
||||||
Margin="0 0 5 0" />
|
Margin="0 0 5 0" />
|
||||||
<TextBox Text="{Binding Value}"
|
<TextBox Text="{Binding UserInput, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
MinWidth="60"
|
||||||
Visibility="{Binding IsConnected, Converter={shared:BooleanToVisibilityConverter Negate=True}}" />
|
Visibility="{Binding IsConnected, Converter={shared:BooleanToVisibilityConverter Negate=True}}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|||||||
@@ -95,10 +95,23 @@ namespace Nodify.Calculator.Execution.Handlers
|
|||||||
var propPath = parenIdx > 0 ? title.Substring(0, parenIdx).Trim() : title.Trim();
|
var propPath = parenIdx > 0 ? title.Substring(0, parenIdx).Trim() : title.Trim();
|
||||||
if (string.IsNullOrEmpty(propPath)) continue;
|
if (string.IsNullOrEmpty(propPath)) continue;
|
||||||
|
|
||||||
var val = ctx.ReadInput(inp);
|
// If a wire is connected → read from upstream node.
|
||||||
|
// Otherwise fall back to whatever the user typed in the inline TextBox (UserInput).
|
||||||
|
// If neither is provided, skip the field so the JSON only carries explicit values.
|
||||||
|
string val;
|
||||||
|
if (inp.IsConnected)
|
||||||
|
{
|
||||||
|
val = ctx.ReadInput(inp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(inp.UserInput)) continue;
|
||||||
|
val = inp.UserInput;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Log($"[NEW OBJECT] {propPath} = {(val?.Length > 80 ? val.Substring(0, 80) + "..." : val ?? "null")}");
|
ctx.Log($"[NEW OBJECT] {propPath} = {(val?.Length > 80 ? val.Substring(0, 80) + "..." : val ?? "null")}");
|
||||||
|
|
||||||
SetNestedValue(root, propPath, val);
|
SetNestedValue(root, propPath, val, inp.DataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
var json = root.ToString(Formatting.None);
|
var json = root.ToString(Formatting.None);
|
||||||
@@ -109,9 +122,10 @@ namespace Nodify.Calculator.Execution.Handlers
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets a value at a dot-notation path in a JObject, creating intermediate objects as needed.
|
/// Sets a value at a dot-notation path in a JObject, creating intermediate objects as needed.
|
||||||
/// e.g., "Address.Street" with value "Main St" → { "Address": { "Street": "Main St" } }
|
/// The leaf token is coerced according to <paramref name="dataType"/> so that string fields
|
||||||
|
/// remain JSON strings, numeric fields remain JSON numbers, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void SetNestedValue(JObject root, string path, string val)
|
private static void SetNestedValue(JObject root, string path, string val, string dataType)
|
||||||
{
|
{
|
||||||
var parts = path.Split('.');
|
var parts = path.Split('.');
|
||||||
var current = root;
|
var current = root;
|
||||||
@@ -129,14 +143,56 @@ namespace Nodify.Calculator.Execution.Handlers
|
|||||||
}
|
}
|
||||||
|
|
||||||
var leaf = parts[parts.Length - 1];
|
var leaf = parts[parts.Length - 1];
|
||||||
if (val != null)
|
current[leaf] = CoerceValue(val, dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JToken CoerceValue(string val, string dataType)
|
||||||
|
{
|
||||||
|
if (val == null) return JValue.CreateNull();
|
||||||
|
|
||||||
|
var dt = (dataType ?? "").Trim().ToLowerInvariant();
|
||||||
|
|
||||||
|
// Lists / nested objects / unspecified — try JSON parse first, fall back to string.
|
||||||
|
if (dt.StartsWith("list<") || dt == "object" || string.IsNullOrEmpty(dt))
|
||||||
{
|
{
|
||||||
try { current[leaf] = JToken.Parse(val); }
|
try { return JToken.Parse(val); }
|
||||||
catch { current[leaf] = val; }
|
catch { return new JValue(val); }
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
switch (dt)
|
||||||
{
|
{
|
||||||
current[leaf] = null;
|
case "string":
|
||||||
|
case "char":
|
||||||
|
case "guid":
|
||||||
|
case "datetime":
|
||||||
|
return new JValue(val);
|
||||||
|
|
||||||
|
case "bool":
|
||||||
|
case "boolean":
|
||||||
|
if (bool.TryParse(val, out var b)) return new JValue(b);
|
||||||
|
return new JValue(val);
|
||||||
|
|
||||||
|
case "int":
|
||||||
|
case "long":
|
||||||
|
case "short":
|
||||||
|
case "byte":
|
||||||
|
if (long.TryParse(val, System.Globalization.NumberStyles.Any,
|
||||||
|
System.Globalization.CultureInfo.InvariantCulture, out var l))
|
||||||
|
return new JValue(l);
|
||||||
|
return new JValue(val);
|
||||||
|
|
||||||
|
case "double":
|
||||||
|
case "float":
|
||||||
|
case "decimal":
|
||||||
|
if (double.TryParse(val, System.Globalization.NumberStyles.Any,
|
||||||
|
System.Globalization.CultureInfo.InvariantCulture, out var d))
|
||||||
|
return new JValue(d);
|
||||||
|
return new JValue(val);
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Custom model type referenced by name → expect a JSON object string.
|
||||||
|
try { return JToken.Parse(val); }
|
||||||
|
catch { return new JValue(val); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user