Skip to content

Commit

Permalink
(GH-3376) Improved handling for percent & permille for NumericUpDown
Browse files Browse the repository at this point in the history
  • Loading branch information
mgnslndh authored and punker76 committed Oct 14, 2019
1 parent 9dcc0de commit 9ee4aea
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 28 deletions.
73 changes: 45 additions & 28 deletions src/MahApps.Metro/Controls/NumericUpDown.cs
Expand Up @@ -190,6 +190,7 @@ private static void InterceptManualEnterChangedCallback(DependencyObject depende
//private static readonly Regex RegexNumber = new Regex(@"[-+]?(?<![0-9][.,])\b[0-9]+(?:[.,\s][0-9]+)*[.,]?[0-9]?(?:[eE][-+]?[0-9]+)?\b(?!\.[0-9])", RegexOptions.Compiled);
private static readonly Regex RegexNumber = new Regex(@"[-+]?(?<![0-9][.,])[.,]?[0-9]+(?:[.,\s][0-9]+)*[.,]?[0-9]?(?:[eE][-+]?[0-9]+)?(?!\.[0-9])", RegexOptions.Compiled);
private static readonly Regex RegexHexadecimal = new Regex(@"^([a-fA-F0-9]{1,2}\s?)+$", RegexOptions.Compiled);
private static readonly Regex RegexStringFormat = new Regex(@"\{0\s*(:(?<format>.*))?\}", RegexOptions.Compiled);

private const double DefaultInterval = 1d;
private const int DefaultDelay = 500;
Expand Down Expand Up @@ -1016,44 +1017,60 @@ private string FormattedValue(double? newValue, string format, CultureInfo cultu
format = format.Replace("{}", string.Empty);
if (!string.IsNullOrWhiteSpace(format))
{
var match = RegexStringFormatHexadecimal.Match(format);
if (match.Success)
if(TryFormatHexadecimal(newValue, format, culture, out string hexValue))
{
if (match.Groups["simpleHEX"].Success)
{
// HEX DOES SUPPORT INT ONLY.
return ((int)newValue.Value).ToString(match.Groups["simpleHEX"].Value, culture);
}

if (match.Groups["complexHEX"].Success)
{
return string.Format(culture, match.Groups["complexHEX"].Value, (int)newValue.Value);
}
return hexValue;
}
else
{
var value = newValue.Value;

if (format.ToUpper().Contains("P") || format.Contains("%"))
{
value = value / 100d;
}
else if (format.Contains(""))
{
value = value / 1000d;
}

if (!format.Contains("{"))
var match = RegexStringFormat.Match(format);
if (match.Success)
{
// then we may have a StringFormat of e.g. "N0"
return value.ToString(format, culture);
// we have a format template such as "{0:N0}"
return string.Format(culture, format, ConvertStringFormatValue(newValue.Value, match.Groups["format"].Value));
}

return string.Format(culture, format, value);
// we have a format such as "N0"
var value = ConvertStringFormatValue(newValue.Value, format);
return value.ToString(format, culture);
}
}

return newValue.Value.ToString(culture);
}

private static double ConvertStringFormatValue(double value, string format)
{
if (format.ToUpper().Contains("P") || format.Contains("%"))
{
value /= 100d;
}
else if (format.Contains(""))
{
value /= 1000d;
}
return value;
}

private bool TryFormatHexadecimal(double? newValue, string format, CultureInfo culture, out string output)
{
var match = RegexStringFormatHexadecimal.Match(format);
if (match.Success)
{
if (match.Groups["simpleHEX"].Success)
{
// HEX DOES SUPPORT INT ONLY.
output = ((int)newValue.Value).ToString(match.Groups["simpleHEX"].Value, culture);
return true;
}

if (match.Groups["complexHEX"].Success)
{
output = string.Format(culture, match.Groups["complexHEX"].Value, (int)newValue.Value);
return true;
}
}
output = null;
return false;
}

private ScrollViewer TryFindScrollViewer()
Expand Down
54 changes: 54 additions & 0 deletions src/Mahapps.Metro.Tests/Tests/NumericUpDownTests.cs
Expand Up @@ -124,6 +124,12 @@ public async Task ShouldConvertTextInputWithStringFormat()
SetText(textBox, "200.00");
Assert.Equal(200d, window.TheNUD.Value);
Assert.Equal("200.00 cm", textBox.Text);

// GH-3551
window.TheNUD.StringFormat = "{}{0}mmHg";
SetText(textBox, "15");
Assert.Equal(15, window.TheNUD.Value);
Assert.Equal("15mmHg", textBox.Text);
}

[Fact]
Expand Down Expand Up @@ -195,6 +201,54 @@ public async Task ShouldConvertTextInputWithPercentStringFormat()
SetText(textBox, "-0.39678");
Assert.Equal(-0.39678d, window.TheNUD.Value);
Assert.Equal("-0.4 %", textBox.Text);

window.TheNUD.StringFormat = "{}{0:0.0%}";
SetText(textBox, "1");
Assert.Equal(1, window.TheNUD.Value);
Assert.Equal("1.0%", textBox.Text);

window.TheNUD.StringFormat = "{0:0.0%}";
SetText(textBox, "1");
Assert.Equal(1, window.TheNUD.Value);
Assert.Equal("1.0%", textBox.Text);

window.TheNUD.StringFormat = "0.0%";
SetText(textBox, "1");
Assert.Equal(1, window.TheNUD.Value);
Assert.Equal("1.0%", textBox.Text);

window.TheNUD.StringFormat = "{}{0:0.0‰}";
SetText(textBox, "1");
Assert.Equal(1, window.TheNUD.Value);
Assert.Equal("1.0‰", textBox.Text);

window.TheNUD.StringFormat = "{0:0.0‰}";
SetText(textBox, "1");
Assert.Equal(1, window.TheNUD.Value);
Assert.Equal("1.0‰", textBox.Text);

window.TheNUD.StringFormat = "0.0‰";
SetText(textBox, "1");
Assert.Equal(1, window.TheNUD.Value);
Assert.Equal("1.0‰", textBox.Text);

// GH-3376 Case 3
window.TheNUD.StringFormat = "{0:0.0000}%";
SetText(textBox, "0.25");
Assert.Equal(0.25, window.TheNUD.Value);
Assert.Equal("0.2500%", textBox.Text);

// GH-3376 Case 4
window.TheNUD.StringFormat = "{0:0.0000}‰";
SetText(textBox, "0.25");
Assert.Equal(0.25, window.TheNUD.Value);
Assert.Equal("0.2500‰", textBox.Text);

// GH-3376#issuecomment-472324787
window.TheNUD.StringFormat = "{}{0:G3} mPa·s";
SetText(textBox, "0.986");
Assert.Equal(0.986, window.TheNUD.Value);
Assert.Equal("0.986 mPa·s", textBox.Text);
}

[Fact]
Expand Down

0 comments on commit 9ee4aea

Please sign in to comment.