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.
This commit is contained in:
Bartłomiej Dach 2021-11-12 23:07:24 +01:00
parent e55e2a1697
commit d567d2be97
No known key found for this signature in database
GPG Key ID: BCECCD4FA41F6497
3 changed files with 28 additions and 21 deletions

View File

@ -19,6 +19,7 @@
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 @@ private void updateTooltipText(T value)
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 @@ protected override void UpdateValue(float value)
/// <returns>The normalised decimal.</returns>
private decimal normalise(decimal d, int sd)
=> decimal.Parse(Math.Round(d, sd).ToString(string.Concat("0.", new string('#', sd)), CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);
/// <summary>
/// Finds the number of digits after the decimal.
/// </summary>
/// <param name="d">The value to find the number of decimal digits for.</param>
/// <returns>The number decimal digits.</returns>
private int findPrecision(decimal d)
{
int precision = 0;
while (d != Math.Round(d))
{
d *= 10;
precision++;
}
return precision;
}
}
}

View File

@ -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.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 @@ public IndeterminateSliderWithTextBoxInput(LocalisableString labelText, Bindable
textbox = new LabelledTextBox
{
Label = labelText,
PlaceholderText = "(multiple)"
},
slider = new SettingsSlider<T>
{
@ -104,11 +105,16 @@ private void updateState()
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)";
}
}
}

View File

@ -31,5 +31,23 @@ public static LocalisableString FormatAccuracy(this double accuracy)
/// </summary>
/// <param name="rank">The rank/position to be formatted.</param>
public static string FormatRank(this int rank) => rank.ToMetric(decimals: rank < 100_000 ? 1 : 0);
/// <summary>
/// Finds the number of digits after the decimal.
/// </summary>
/// <param name="d">The value to find the number of decimal digits for.</param>
/// <returns>The number decimal digits.</returns>
public static int FindPrecision(decimal d)
{
int precision = 0;
while (d != Math.Round(d))
{
d *= 10;
precision++;
}
return precision;
}
}
}