]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Fix atmos UI decimal separator bug (#23009)
authorKot <1192090+koteq@users.noreply.github.com>
Fri, 5 Jan 2024 05:18:09 +0000 (09:18 +0400)
committerGitHub <noreply@github.com>
Fri, 5 Jan 2024 05:18:09 +0000 (21:18 -0800)
* Fix atmos UI inconsistent culture usage

* Remove the need to pass localization manager

14 files changed:
Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs
Content.Client/Atmos/UI/GasFilterWindow.xaml
Content.Client/Atmos/UI/GasFilterWindow.xaml.cs
Content.Client/Atmos/UI/GasMixerBoundUserInteface.cs
Content.Client/Atmos/UI/GasMixerWindow.xaml
Content.Client/Atmos/UI/GasMixerWindow.xaml.cs
Content.Client/Atmos/UI/GasPressurePumpBoundUserInterface.cs
Content.Client/Atmos/UI/GasPressurePumpWindow.xaml
Content.Client/Atmos/UI/GasPressurePumpWindow.xaml.cs
Content.Client/Atmos/UI/GasVolumePumpBoundUserInterface.cs
Content.Client/Atmos/UI/GasVolumePumpWindow.xaml
Content.Client/Atmos/UI/GasVolumePumpWindow.xaml.cs
Content.Shared/Localizations/UserInputParser.cs [new file with mode: 0644]
Content.Tests/Shared/Localizations/UserInputParserTest.cs [new file with mode: 0644]

index 1087efd51d1ee2fcde3ebc20c4161d62e9848a2b..1904e2b3402a041f82a8a44ec9010dfa18131991 100644 (file)
@@ -1,8 +1,8 @@
 using Content.Client.Atmos.EntitySystems;
 using Content.Shared.Atmos;
 using Content.Shared.Atmos.Piping.Trinary.Components;
+using Content.Shared.Localizations;
 using JetBrains.Annotations;
-using Robust.Client.GameObjects;
 
 namespace Content.Client.Atmos.UI
 {
@@ -50,7 +50,7 @@ namespace Content.Client.Atmos.UI
 
         private void OnFilterTransferRatePressed(string value)
         {
-            float rate = float.TryParse(value, out var parsed) ? parsed : 0f;
+            var rate = UserInputParser.TryFloat(value, out var parsed) ? parsed : 0f;
 
             SendMessage(new GasFilterChangeRateMessage(rate));
         }
index 6963a71d3d476b6a47056c5127f9913840ffbe6e..861d4473089e176c517981e5dac78b35b4a9b930 100644 (file)
@@ -9,7 +9,7 @@
 
         <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
             <Label Text="{Loc comp-gas-filter-ui-filter-transfer-rate}"/>
-            <LineEdit Name="FilterTransferRateInput" MinSize="60 0" />
+            <LineEdit Name="FilterTransferRateInput" MinSize="70 0" />
             <Button Name="SetFilterRate" Text="{Loc comp-gas-filter-ui-filter-set-rate}" Disabled="True"/>
         </BoxContainer>
 
index 74cef4b39b4dceba3a3a7169523fda11f1579cb6..28766c688a0ede11d61484bb2fd6b1984466ab78 100644 (file)
@@ -49,7 +49,7 @@ namespace Content.Client.Atmos.UI
 
         public void SetTransferRate(float rate)
         {
-            FilterTransferRateInput.Text = rate.ToString(CultureInfo.InvariantCulture);
+            FilterTransferRateInput.Text = rate.ToString(CultureInfo.CurrentCulture);
         }
 
         public void SetFilterStatus(bool enabled)
index cfec8c349588b4ec09a881bbd7ea8f83eb56a946..709c06517cb310c505a2d6369343e67768eb364a 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Shared.Atmos;
 using Content.Shared.Atmos.Piping.Trinary.Components;
+using Content.Shared.Localizations;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
 
@@ -47,7 +48,7 @@ namespace Content.Client.Atmos.UI
 
         private void OnMixerOutputPressurePressed(string value)
         {
-            var pressure = float.TryParse(value, out var parsed) ? parsed : 0f;
+            var pressure = UserInputParser.TryFloat(value, out var parsed) ? parsed : 0f;
             if (pressure > MaxPressure)
                 pressure = MaxPressure;
 
@@ -57,7 +58,7 @@ namespace Content.Client.Atmos.UI
         private void OnMixerSetPercentagePressed(string value)
         {
             // We don't need to send both nodes because it's just 100.0f - node
-            var node = float.TryParse(value, out var parsed) ? parsed : 1.0f;
+            var node = UserInputParser.TryFloat(value, out var parsed) ? parsed : 1.0f;
 
             node = Math.Clamp(node, 0f, 100.0f);
 
index 7e74348962a72aee6b2f6fd1c7fc576603b5c513..cebca597472ce34f1ec6a899ed92eac0d4be87b0 100644 (file)
@@ -10,7 +10,7 @@
         <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
             <Label Text="{Loc comp-gas-mixer-ui-mixer-output-pressure}"/>
             <Control MinSize="5 0" />
-            <LineEdit Name="MixerPressureOutputInput" MinSize="60 0" />
+            <LineEdit Name="MixerPressureOutputInput" MinSize="70 0" />
             <Control MinSize="5 0" />
             <Button Name="SetMaxPressureButton" Text="{Loc comp-gas-mixer-ui-mixer-max}" />
             <Control MinSize="5 0" />
index f3f8293bc816737fdc1dcebd552ab3023f5aa5b3..8ff7b8cfa30d044c21a9c174b398a39e99f2a8f5 100644 (file)
@@ -45,7 +45,7 @@ namespace Content.Client.Atmos.UI
 
             SetMaxPressureButton.OnPressed += _ =>
             {
-                MixerPressureOutputInput.Text = Atmospherics.MaxOutputPressure.ToString(CultureInfo.InvariantCulture);
+                MixerPressureOutputInput.Text = Atmospherics.MaxOutputPressure.ToString(CultureInfo.CurrentCulture);
                 SetOutputPressureButton.Disabled = false;
             };
 
@@ -69,16 +69,16 @@ namespace Content.Client.Atmos.UI
 
         public void SetOutputPressure(float pressure)
         {
-            MixerPressureOutputInput.Text = pressure.ToString(CultureInfo.InvariantCulture);
+            MixerPressureOutputInput.Text = pressure.ToString(CultureInfo.CurrentCulture);
         }
 
         public void SetNodePercentages(float nodeOne)
         {
             nodeOne *= 100.0f;
-            MixerNodeOneInput.Text = nodeOne.ToString("0.##", CultureInfo.InvariantCulture);
+            MixerNodeOneInput.Text = nodeOne.ToString("0.##", CultureInfo.CurrentCulture);
 
             float nodeTwo = 100.0f - nodeOne;
-            MixerNodeTwoInput.Text = nodeTwo.ToString("0.##", CultureInfo.InvariantCulture);
+            MixerNodeTwoInput.Text = nodeTwo.ToString("0.##", CultureInfo.CurrentCulture);
         }
 
         public void SetMixerStatus(bool enabled)
index 69cd6cb587e3caf7982e729d20ec6b6f85bf2b03..6eba2e0d2154114e360d46469d64f2a097a7a621 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Shared.Atmos;
 using Content.Shared.Atmos.Piping.Binary.Components;
+using Content.Shared.Localizations;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
 
@@ -46,7 +47,7 @@ namespace Content.Client.Atmos.UI
 
         private void OnPumpOutputPressurePressed(string value)
         {
-            float pressure = float.TryParse(value, out var parsed) ? parsed : 0f;
+            var pressure = UserInputParser.TryFloat(value, out var parsed) ? parsed : 0f;
             if (pressure > MaxPressure) pressure = MaxPressure;
 
             SendMessage(new GasPressurePumpChangeOutputPressureMessage(pressure));
index 8be7a84e86ccd1d0b8eaa45f4a75f0ba7f1c18f1..a0896a7b41e7b7971b5a3e8b642f4e820701c335 100644 (file)
@@ -11,7 +11,7 @@
         <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
             <Label Text="{Loc comp-gas-pump-ui-pump-output-pressure}"/>
             <Control MinSize="5 0" />
-            <LineEdit Name="PumpPressureOutputInput" MinSize="60 0" />
+            <LineEdit Name="PumpPressureOutputInput" MinSize="70 0" />
             <Control MinSize="5 0" />
             <Button Name="SetMaxPressureButton" Text="{Loc comp-gas-pump-ui-pump-set-max}" />
             <Control MinSize="5 0" />
index 22d8a1e9dfcde4bb74f5883be148ae8279d4efea..b5ffcd10721e705a7c3e4deaf2bcec41919d1ba4 100644 (file)
@@ -39,14 +39,14 @@ namespace Content.Client.Atmos.UI
 
             SetMaxPressureButton.OnPressed += _ =>
             {
-                PumpPressureOutputInput.Text = Atmospherics.MaxOutputPressure.ToString(CultureInfo.InvariantCulture);
+                PumpPressureOutputInput.Text = Atmospherics.MaxOutputPressure.ToString(CultureInfo.CurrentCulture);
                 SetOutputPressureButton.Disabled = false;
             };
         }
 
         public void SetOutputPressure(float pressure)
         {
-            PumpPressureOutputInput.Text = pressure.ToString(CultureInfo.InvariantCulture);
+            PumpPressureOutputInput.Text = pressure.ToString(CultureInfo.CurrentCulture);
         }
 
         public void SetPumpStatus(bool enabled)
index 5ccc79a410fa661828e8ba7b7c0f9591c9d460fd..1b39306181a1c52911e63fb502bece3c8422d533 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Shared.Atmos;
 using Content.Shared.Atmos.Piping.Binary.Components;
+using Content.Shared.Localizations;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
 
@@ -46,7 +47,7 @@ namespace Content.Client.Atmos.UI
 
         private void OnPumpTransferRatePressed(string value)
         {
-            var rate = float.TryParse(value, out var parsed) ? parsed : 0f;
+            var rate = UserInputParser.TryFloat(value, out var parsed) ? parsed : 0f;
             if (rate > MaxTransferRate)
                 rate = MaxTransferRate;
 
index 93ebc35a93bffaad23bbcb7a25ae982db71effc8..7275b34b3ad0782bab7baf1c2e0e474ccaa0e742 100644 (file)
@@ -11,7 +11,7 @@
         <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
             <Label Text="{Loc comp-gas-pump-ui-pump-transfer-rate}"/>
             <Control MinSize="5 0" />
-            <LineEdit Name="PumpTransferRateInput" MinSize="60 0" />
+            <LineEdit Name="PumpTransferRateInput" MinSize="70 0" />
             <Control MinSize="5 0" />
             <Button Name="SetMaxRateButton" Text="{Loc comp-gas-pump-ui-pump-set-max}" />
             <Control MinSize="5 0" />
index 2ca567302ddfd5244e4c35df1dee072027bb38a4..83a530c5c5a5a9780e9337971c5a6b625efff2d7 100644 (file)
@@ -39,14 +39,14 @@ namespace Content.Client.Atmos.UI
 
             SetMaxRateButton.OnPressed += _ =>
             {
-                PumpTransferRateInput.Text = Atmospherics.MaxTransferRate.ToString(CultureInfo.InvariantCulture);
+                PumpTransferRateInput.Text = Atmospherics.MaxTransferRate.ToString(CultureInfo.CurrentCulture);
                 SetTransferRateButton.Disabled = false;
             };
         }
 
         public void SetTransferRate(float rate)
         {
-            PumpTransferRateInput.Text = rate.ToString(CultureInfo.InvariantCulture);
+            PumpTransferRateInput.Text = rate.ToString(CultureInfo.CurrentCulture);
         }
 
         public void SetPumpStatus(bool enabled)
diff --git a/Content.Shared/Localizations/UserInputParser.cs b/Content.Shared/Localizations/UserInputParser.cs
new file mode 100644 (file)
index 0000000..0aaf44a
--- /dev/null
@@ -0,0 +1,54 @@
+using System.Globalization;
+
+namespace Content.Shared.Localizations;
+
+/// <summary>
+/// Helpers for user input parsing.
+/// </summary>
+/// <remarks>
+/// A wrapper around the <see cref="System.Single.TryParse(string, out float)"/> API,
+/// with the goal of trying more options to make the user input parsing less restrictive.
+/// For culture-invariant parsing use <see cref="Robust.Shared.Utility.Parse"/>.
+/// </remarks>
+public static class UserInputParser
+{
+    private static readonly NumberFormatInfo[] StandardDecimalNumberFormats = new[]
+    {
+        new NumberFormatInfo()
+        {
+            NumberDecimalSeparator = "."
+        },
+        new NumberFormatInfo()
+        {
+            NumberDecimalSeparator = ","
+        }
+    };
+
+    public static bool TryFloat(ReadOnlySpan<char> text, out float result)
+    {
+        foreach (var format in StandardDecimalNumberFormats)
+        {
+            if (float.TryParse(text, NumberStyles.Integer | NumberStyles.AllowDecimalPoint, format, out result))
+            {
+                return true;
+            }
+        }
+
+        result = 0f;
+        return false;
+    }
+
+    public static bool TryDouble(ReadOnlySpan<char> text, out double result)
+    {
+        foreach (var format in StandardDecimalNumberFormats)
+        {
+            if (double.TryParse(text, NumberStyles.Integer | NumberStyles.AllowDecimalPoint, format, out result))
+            {
+                return true;
+            }
+        }
+
+        result = 0d;
+        return false;
+    }
+}
diff --git a/Content.Tests/Shared/Localizations/UserInputParserTest.cs b/Content.Tests/Shared/Localizations/UserInputParserTest.cs
new file mode 100644 (file)
index 0000000..883fb00
--- /dev/null
@@ -0,0 +1,41 @@
+using Content.Shared.Localizations;
+using NUnit.Framework;
+
+namespace Content.Tests.Shared.Localizations
+{
+    [TestFixture]
+    public sealed class UserInputParserTest
+    {
+        [Test]
+        [TestCase("1234.56", 1234.56f, true)]
+        [TestCase("1234,56", 1234.56f, true)]
+        [TestCase(" +1234.56 ", 1234.56f, true)]
+        [TestCase(" -1234.56 ", -1234.56f, true)]
+        [TestCase("1234.56e7", 0f, false)]
+        [TestCase("1,234.56", 0f, false)]
+        [TestCase("1 234,56", 0f, false)]
+        public void TryFloatTest(string input, float expectedOutput, bool expectedResult)
+        {
+            var result = UserInputParser.TryFloat(input, out var output);
+
+            Assert.That(result, Is.EqualTo(expectedResult));
+            Assert.That(output, Is.EqualTo(expectedOutput).Within(float.Epsilon));
+        }
+
+        [Test]
+        [TestCase("1234.56", 1234.56d, true)]
+        [TestCase("1234,56", 1234.56d, true)]
+        [TestCase(" +1234.56 ", 1234.56d, true)]
+        [TestCase(" -1234.56 ", -1234.56d, true)]
+        [TestCase("1234.56e7", 0d, false)]
+        [TestCase("1,234.56", 0d, false)]
+        [TestCase("1 234,56", 0d, false)]
+        public void TryDoubleTest(string input, double expectedOutput, bool expectedResult)
+        {
+            var result = UserInputParser.TryDouble(input, out var output);
+
+            Assert.That(result, Is.EqualTo(expectedResult));
+            Assert.That(output, Is.EqualTo(expectedOutput).Within(double.Epsilon));
+        }
+    }
+}