diff --git a/Coder.Graph/AstGraphEditor.cs b/Coder.Graph/AstGraphEditor.cs index 8834913..62c9e81 100644 --- a/Coder.Graph/AstGraphEditor.cs +++ b/Coder.Graph/AstGraphEditor.cs @@ -50,7 +50,7 @@ public sealed class AstGraphEditor(AstNode root) /// sits beside the graph, and the names it draws — Visibility, Parameters — are /// longer than most of the values beside them. It stays the user's to drag either way. /// - /// Fractions are spelled to fifteen significant digits rather than the widget's six decimal + /// Fractions are spelled to seventeen significant digits rather than the widget's six decimal /// places. A literal is a value the generated source will carry, so the row has to show what the /// document holds: 3.14 has to read as 3.14 rather than as 3.140000, and a value with more digits /// than that has to keep them when the user opens the box to change something else about it. @@ -59,7 +59,7 @@ public sealed class AstGraphEditor(AstNode root) private static readonly ImGuiWidgets.PropertyGridOptions InspectorGridOptions = new() { LabelColumnWeight = 0.95f, - DoubleFormat = "%.15g", + DoubleFormat = "%.17g", }; private string statusMessage = string.Empty; diff --git a/Coder.Test/Graph/AstGraphEditorInspectorPanelTests.cs b/Coder.Test/Graph/AstGraphEditorInspectorPanelTests.cs index f48721c..aaefb9f 100644 --- a/Coder.Test/Graph/AstGraphEditorInspectorPanelTests.cs +++ b/Coder.Test/Graph/AstGraphEditorInspectorPanelTests.cs @@ -2,6 +2,8 @@ namespace ktsu.Coder.Test.Graph; +using System.Globalization; +using System.Reflection; using System.Numerics; using Hexa.NET.ImGui; @@ -42,6 +44,14 @@ private static FunctionDeclaration SampleFunction() return function; } + private static (FunctionDeclaration Function, LiteralExpression Literal) SampleFunctionWithSmallFractionLiteral() + { + LiteralExpression literal = Literal.DecimalValue(1e-9); + FunctionDeclaration function = new("tiny") { ReturnType = "double" }; + function.Body.Add(new ReturnStatement(literal)); + return (function, literal); + } + /// /// Draws the whole editor, because selecting a node is ImNodes' business and it faults inside /// native code when its context is missing rather than throwing. @@ -207,4 +217,40 @@ public void Inspector_AddsAndRemovesChildrenFromASlotRow() Assert.HasCount(1, function.Parameters); } + + /// + /// Tests that a tiny floating-point literal keeps its value through inspector draws and edit + /// commits, rather than being collapsed to zero by the row's display format. + /// + [TestMethod] + public void Inspector_PreservesASmallFractionLiteralAcrossDrawAndEdit() + { + FieldInfo optionsField = typeof(AstGraphEditor).GetField("InspectorGridOptions", BindingFlags.NonPublic | BindingFlags.Static) + ?? throw new AssertFailedException("Inspector grid options should exist."); + + ktsu.ImGui.Widgets.ImGuiWidgets.PropertyGridOptions options = + (ktsu.ImGui.Widgets.ImGuiWidgets.PropertyGridOptions)optionsField.GetValue(null)!; + Assert.AreEqual("%.17g", options.DoubleFormat); + + (FunctionDeclaration function, LiteralExpression literal) = SampleFunctionWithSmallFractionLiteral(); + AstGraphEditor editor = new(function); + double expected = literal.Value; + + using ImGuiAppHarness harness = Inspecting(editor, literal); + + // Rendering and selecting the node must leave the document value untouched. + Assert.AreEqual(expected, literal.Value); + + harness.Click("Value"); + harness.Step(2); + + harness.Keyboard.Press(ImGuiKey.A, ctrl: true); + harness.Keyboard.Type(expected.ToString("G17", CultureInfo.InvariantCulture)); + harness.Step(2); + + harness.Keyboard.Press(ImGuiKey.Enter); + harness.Step(2); + + Assert.AreEqual(expected, literal.Value); + } }