mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 13:28:16 +08:00

committed by
Patrik Svensson

parent
1cf30f62fc
commit
7dccb310f3
82
src/Spectre.Console/Widgets/BarChart.cs
Normal file
82
src/Spectre.Console/Widgets/BarChart.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// A renderable (horizontal) bar chart.
|
||||
/// </summary>
|
||||
public sealed class BarChart : Renderable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the bar chart data.
|
||||
/// </summary>
|
||||
public List<BarChartItem> 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>
|
||||
/// Initializes a new instance of the <see cref="BarChart"/> class.
|
||||
/// </summary>
|
||||
public BarChart()
|
||||
{
|
||||
Data = new List<BarChartItem>();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
|
||||
{
|
||||
var maxValue = Data.Max(item => item.Value);
|
||||
|
||||
var table = new Grid();
|
||||
table.Collapse();
|
||||
table.AddColumn(new GridColumn().PadRight(2).RightAligned());
|
||||
table.AddColumn(new GridColumn().PadLeft(0));
|
||||
table.Width = Width;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Label))
|
||||
{
|
||||
table.AddRow(Text.Empty, new Markup(Label).Alignment(LabelAlignment));
|
||||
}
|
||||
|
||||
foreach (var item in Data)
|
||||
{
|
||||
table.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,
|
||||
});
|
||||
}
|
||||
|
||||
return ((IRenderable)table).Render(context, maxWidth);
|
||||
}
|
||||
}
|
||||
}
|
38
src/Spectre.Console/Widgets/BarChartItem.cs
Normal file
38
src/Spectre.Console/Widgets/BarChartItem.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// An item that's shown in a bar chart.
|
||||
/// </summary>
|
||||
public sealed class BarChartItem : IBarChartItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the item label.
|
||||
/// </summary>
|
||||
public string Label { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item value.
|
||||
/// </summary>
|
||||
public double Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item color.
|
||||
/// </summary>
|
||||
public Color? Color { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarChartItem"/> class.
|
||||
/// </summary>
|
||||
/// <param name="label">The item label.</param>
|
||||
/// <param name="value">The item value.</param>
|
||||
/// <param name="color">The item color.</param>
|
||||
public BarChartItem(string label, double value, Color? color = null)
|
||||
{
|
||||
Label = label ?? throw new ArgumentNullException(nameof(label));
|
||||
Value = value;
|
||||
Color = color;
|
||||
}
|
||||
}
|
||||
}
|
@ -42,6 +42,11 @@ namespace Spectre.Console
|
||||
set => MarkAsDirty(() => _alignment = value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the grid.
|
||||
/// </summary>
|
||||
public int? Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Grid"/> class.
|
||||
/// </summary>
|
||||
@ -124,6 +129,7 @@ namespace Spectre.Console
|
||||
ShowHeaders = false,
|
||||
IsGrid = true,
|
||||
PadRightCell = _padRightCell,
|
||||
Width = Width,
|
||||
};
|
||||
|
||||
foreach (var column in _columns)
|
||||
|
23
src/Spectre.Console/Widgets/IBarGraphItem.cs
Normal file
23
src/Spectre.Console/Widgets/IBarGraphItem.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a bar chart item.
|
||||
/// </summary>
|
||||
public interface IBarChartItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the item label.
|
||||
/// </summary>
|
||||
string Label { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item value.
|
||||
/// </summary>
|
||||
double Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item color.
|
||||
/// </summary>
|
||||
Color? Color { get; }
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
@ -10,6 +11,10 @@ namespace Spectre.Console
|
||||
public double MaxValue { get; set; } = 100;
|
||||
|
||||
public int? Width { get; set; }
|
||||
public bool ShowRemaining { get; set; } = true;
|
||||
public char UnicodeBar { get; set; } = '━';
|
||||
public char AsciiBar { get; set; } = '-';
|
||||
public bool ShowValue { get; set; }
|
||||
|
||||
public Style CompletedStyle { get; set; } = new Style(foreground: Color.Yellow);
|
||||
public Style FinishedStyle { get; set; } = new Style(foreground: Color.Green);
|
||||
@ -26,15 +31,38 @@ namespace Spectre.Console
|
||||
var width = Math.Min(Width ?? maxWidth, maxWidth);
|
||||
var completed = Math.Min(MaxValue, Math.Max(0, Value));
|
||||
|
||||
var token = !context.Unicode || context.LegacyConsole ? '-' : '━';
|
||||
var token = !context.Unicode || context.LegacyConsole ? AsciiBar : UnicodeBar;
|
||||
var style = completed >= MaxValue ? FinishedStyle : CompletedStyle;
|
||||
|
||||
var bars = Math.Max(0, (int)(width * (completed / MaxValue)));
|
||||
|
||||
var value = completed.ToString(CultureInfo.InvariantCulture);
|
||||
if (ShowValue)
|
||||
{
|
||||
bars = bars - value.Length - 1;
|
||||
}
|
||||
|
||||
yield return new Segment(new string(token, bars), style);
|
||||
|
||||
if (ShowValue)
|
||||
{
|
||||
yield return new Segment(" " + value, style);
|
||||
}
|
||||
|
||||
if (bars < width)
|
||||
{
|
||||
yield return new Segment(new string(token, width - bars), RemainingStyle);
|
||||
var diff = width - bars;
|
||||
if (ShowValue)
|
||||
{
|
||||
diff = diff - value.Length - 1;
|
||||
if (diff <= 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
var remainingToken = ShowRemaining ? token : ' ';
|
||||
yield return new Segment(new string(remainingToken, diff), RemainingStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user