diff --git a/examples/Console/Charts/Program.cs b/examples/Console/Charts/Program.cs index c44554b..229047f 100644 --- a/examples/Console/Charts/Program.cs +++ b/examples/Console/Charts/Program.cs @@ -19,10 +19,10 @@ namespace Charts // Render a breakdown chart AnsiConsole.WriteLine(); - Render("Languages", new BreakdownChart() + Render("Languages used", new BreakdownChart() .FullSize() .Width(60) - .TagValueFormat("{0}%") + .ShowPercentage() .AddItem("SCSS", 37, Color.Red) .AddItem("HTML", 28.3, Color.Blue) .AddItem("C#", 22.6, Color.Green) diff --git a/src/Spectre.Console.Tests/Unit/BreakdownChartTests.cs b/src/Spectre.Console.Tests/Unit/BreakdownChartTests.cs index 160b1af..b16991b 100644 --- a/src/Spectre.Console.Tests/Unit/BreakdownChartTests.cs +++ b/src/Spectre.Console.Tests/Unit/BreakdownChartTests.cs @@ -42,14 +42,14 @@ namespace Spectre.Console.Tests.Unit [Fact] [Expectation("TagFormat")] - public async Task Should_Render_Correctly_With_Specific_Tag_Formatter() + public async Task Should_Render_Correctly_With_Specific_Value_Formatter() { // Given var console = new FakeConsole(width: 80); var chart = Fixture.GetChart() .Width(60) .Culture("sv-SE") - .TagValueFormat("{0}%"); + .UseValueFormatter((v, c) => string.Format(c, "{0}%", v)); // When console.Render(chart); diff --git a/src/Spectre.Console/Extensions/BreakdownChartExtensions.cs b/src/Spectre.Console/Extensions/BreakdownChartExtensions.cs index 5c7a2e1..e19bb43 100644 --- a/src/Spectre.Console/Extensions/BreakdownChartExtensions.cs +++ b/src/Spectre.Console/Extensions/BreakdownChartExtensions.cs @@ -141,16 +141,53 @@ namespace Spectre.Console /// Tags will be shown. /// /// The breakdown chart. - /// The tag value format. + /// The value formatter to use. /// The same instance so that multiple calls can be chained. - public static BreakdownChart TagValueFormat(this BreakdownChart chart, string? format) + public static BreakdownChart UseValueFormatter(this BreakdownChart chart, Func? func) { if (chart is null) { throw new ArgumentNullException(nameof(chart)); } - chart.TagValueFormat = format; + chart.ValueFormatter = func; + return chart; + } + + /// + /// Tags will be shown. + /// + /// The breakdown chart. + /// The value formatter to use. + /// The same instance so that multiple calls can be chained. + public static BreakdownChart UseValueFormatter(this BreakdownChart chart, Func? func) + { + if (chart is null) + { + throw new ArgumentNullException(nameof(chart)); + } + + chart.ValueFormatter = func != null + ? (value, _) => func(value) + : null; + + return chart; + } + + /// + /// Tags will be shown. + /// + /// The breakdown chart. + /// The same instance so that multiple calls can be chained. + public static BreakdownChart ShowPercentage(this BreakdownChart chart) + { + if (chart is null) + { + throw new ArgumentNullException(nameof(chart)); + } + + chart.ValueFormatter = (value, culture) => string.Format(culture, "{0}%", value); + return chart; } diff --git a/src/Spectre.Console/Widgets/Charts/BreakdownChart.cs b/src/Spectre.Console/Widgets/Charts/BreakdownChart.cs index 74f972f..b7b6708 100644 --- a/src/Spectre.Console/Widgets/Charts/BreakdownChart.cs +++ b/src/Spectre.Console/Widgets/Charts/BreakdownChart.cs @@ -31,9 +31,9 @@ namespace Spectre.Console public bool ShowTagValues { get; set; } = true; /// - /// Gets or sets the tag value format. + /// Gets or sets the tag value formatter. /// - public string? TagValueFormat { get; set; } + public Func? ValueFormatter { get; set; } /// /// Gets or sets a value indicating whether or not the @@ -91,7 +91,7 @@ namespace Spectre.Console Width = width, Culture = Culture, ShowTagValues = ShowTagValues, - TagValueFormat = TagValueFormat, + ValueFormatter = ValueFormatter, }); } diff --git a/src/Spectre.Console/Widgets/Charts/BreakdownTags.cs b/src/Spectre.Console/Widgets/Charts/BreakdownTags.cs index cec47f9..9fc5fcd 100644 --- a/src/Spectre.Console/Widgets/Charts/BreakdownTags.cs +++ b/src/Spectre.Console/Widgets/Charts/BreakdownTags.cs @@ -12,7 +12,7 @@ namespace Spectre.Console public int? Width { get; set; } public CultureInfo? Culture { get; set; } public bool ShowTagValues { get; set; } = true; - public string? TagValueFormat { get; set; } + public Func? ValueFormatter { get; set; } public BreakdownTags(List data) { @@ -56,16 +56,21 @@ namespace Spectre.Console private string FormatValue(IBreakdownChartItem item, CultureInfo culture) { - var formatter = TagValueFormat ?? "{0}"; + var formatter = ValueFormatter ?? DefaultFormatter; if (ShowTagValues) { return string.Format(culture, "{0} [grey]{1}[/]", item.Label.EscapeMarkup(), - string.Format(culture, formatter, item.Value)); + formatter(item.Value, culture)); } return item.Label.EscapeMarkup(); } + + private static string DefaultFormatter(double value, CultureInfo culture) + { + return value.ToString(culture); + } } } diff --git a/src/Spectre.Console/Widgets/ProgressBar.cs b/src/Spectre.Console/Widgets/ProgressBar.cs index f54cb2a..0021b1b 100644 --- a/src/Spectre.Console/Widgets/ProgressBar.cs +++ b/src/Spectre.Console/Widgets/ProgressBar.cs @@ -44,6 +44,11 @@ namespace Spectre.Console bars = Math.Max(0, bars); } + if (bars < 0) + { + yield break; + } + yield return new Segment(new string(token, bars), style); if (ShowValue)