From d567d2be973cd860122454bfbb64b7150ef0a8b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 12 Nov 2021 23:07:24 +0100 Subject: [PATCH] Fix multiple issues with textbox content display - Sometimes would display too many decimal digits due to floating point representation errors. - Placeholder would also look wrong if text was removed during a multiple (but determinate) selection. --- .../Graphics/UserInterface/OsuSliderBar.cs | 21 ++----------------- .../IndeterminateSliderWithTextBoxInput.cs | 10 +++++++-- osu.Game/Utils/FormatUtils.cs | 18 ++++++++++++++++ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index d4310dc901..333ae4f832 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -19,6 +19,7 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Game.Overlays; +using osu.Game.Utils; namespace osu.Game.Graphics.UserInterface { @@ -219,7 +220,7 @@ namespace osu.Game.Graphics.UserInterface decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits); // Find the number of significant digits (we could have less than 5 after normalize()) - int significantDigits = findPrecision(decimalPrecision); + int significantDigits = FormatUtils.FindPrecision(decimalPrecision); TooltipText = floatValue.ToString($"N{significantDigits}"); } @@ -248,23 +249,5 @@ namespace osu.Game.Graphics.UserInterface /// The normalised decimal. private decimal normalise(decimal d, int sd) => decimal.Parse(Math.Round(d, sd).ToString(string.Concat("0.", new string('#', sd)), CultureInfo.InvariantCulture), CultureInfo.InvariantCulture); - - /// - /// Finds the number of digits after the decimal. - /// - /// The value to find the number of decimal digits for. - /// The number decimal digits. - private int findPrecision(decimal d) - { - int precision = 0; - - while (d != Math.Round(d)) - { - d *= 10; - precision++; - } - - return precision; - } } } diff --git a/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs b/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs index a5c682e56a..17f82f4978 100644 --- a/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs +++ b/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Globalization; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -9,6 +10,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays.Settings; +using osu.Game.Utils; namespace osu.Game.Screens.Edit.Timing { @@ -65,7 +67,6 @@ namespace osu.Game.Screens.Edit.Timing textbox = new LabelledTextBox { Label = labelText, - PlaceholderText = "(multiple)" }, slider = new SettingsSlider { @@ -104,11 +105,16 @@ namespace osu.Game.Screens.Edit.Timing if (Current.Value is T nonNullValue) { slider.Current.Value = nonNullValue; - textbox.Text = slider.Current.ToString(); + + // use the value from the slider to ensure that any precision/min/max set on it via the initial indeterminate value have been applied correctly. + decimal decimalValue = slider.Current.Value.ToDecimal(NumberFormatInfo.InvariantInfo); + textbox.Text = decimalValue.ToString($@"N{FormatUtils.FindPrecision(decimalValue)}"); + textbox.PlaceholderText = string.Empty; } else { textbox.Text = null; + textbox.PlaceholderText = "(multiple)"; } } } diff --git a/osu.Game/Utils/FormatUtils.cs b/osu.Game/Utils/FormatUtils.cs index d14dbb49f3..799dc75ca9 100644 --- a/osu.Game/Utils/FormatUtils.cs +++ b/osu.Game/Utils/FormatUtils.cs @@ -31,5 +31,23 @@ namespace osu.Game.Utils /// /// The rank/position to be formatted. public static string FormatRank(this int rank) => rank.ToMetric(decimals: rank < 100_000 ? 1 : 0); + + /// + /// Finds the number of digits after the decimal. + /// + /// The value to find the number of decimal digits for. + /// The number decimal digits. + public static int FindPrecision(decimal d) + { + int precision = 0; + + while (d != Math.Round(d)) + { + d *= 10; + precision++; + } + + return precision; + } } }