2024-01-31 17:37:05 +01:00

104 lines
3.2 KiB
C#

namespace Spectre.Console;
/// <summary>
/// A renderable (horizontal) bar chart.
/// </summary>
public sealed class BarChart : Renderable, IHasCulture
{
/// <summary>
/// Gets the bar chart data.
/// </summary>
public List<IBarChartItem> Data { get; }
/// <summary>
/// Gets or sets the width of the bar chart.
/// </summary>
public int? Width { get; set; }
/// <summary>
/// Gets or sets the bar chart label.
/// </summary>
public string? Label { get; set; }
/// <summary>
/// Gets or sets the bar chart label alignment.
/// </summary>
public Justify? LabelAlignment { get; set; } = Justify.Center;
/// <summary>
/// Gets or sets a value indicating whether or not
/// values should be shown next to each bar.
/// </summary>
public bool ShowValues { get; set; } = true;
/// <summary>
/// Gets or sets the culture that's used to format values.
/// </summary>
/// <remarks>Defaults to invariant culture.</remarks>
public CultureInfo? Culture { get; set; }
/// <summary>
/// Gets or sets the fixed max value for a bar chart.
/// </summary>
/// <remarks>Defaults to null, which corresponds to largest value in chart.</remarks>
public double? MaxValue { get; set; }
/// <summary>
/// Gets or sets the function used to format the values of the bar chart.
/// </summary>
public Func<double, CultureInfo, string>? ValueFormatter { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="BarChart"/> class.
/// </summary>
public BarChart()
{
Data = new List<IBarChartItem>();
}
/// <inheritdoc/>
protected override Measurement Measure(RenderOptions options, int maxWidth)
{
var width = Math.Min(Width ?? maxWidth, maxWidth);
return new Measurement(width, width);
}
/// <inheritdoc/>
protected override IEnumerable<Segment> Render(RenderOptions options, int maxWidth)
{
var width = Math.Min(Width ?? maxWidth, maxWidth);
var maxValue = Math.Max(MaxValue ?? 0d, Data.Max(item => item.Value));
var grid = new Grid();
grid.Collapse();
grid.AddColumn(new GridColumn().PadRight(2).RightAligned());
grid.AddColumn(new GridColumn().PadLeft(0));
grid.Width = width;
if (!string.IsNullOrWhiteSpace(Label))
{
grid.AddRow(Text.Empty, new Markup(Label).Justify(LabelAlignment));
}
foreach (var item in Data)
{
grid.AddRow(
new Markup(item.Label),
new ProgressBar()
{
Value = item.Value,
MaxValue = maxValue,
ShowRemaining = false,
CompletedStyle = new Style().Foreground(item.Color ?? Color.Default),
FinishedStyle = new Style().Foreground(item.Color ?? Color.Default),
UnicodeBar = '█',
AsciiBar = '█',
ShowValue = ShowValues,
Culture = Culture,
ValueFormatter = ValueFormatter,
});
}
return ((IRenderable)grid).Render(options, width);
}
}