Add breakdown chart support

This also cleans up the bar chart code slightly and fixes
some minor bugs that were detected in related code.

Closes #244
This commit is contained in:
Patrik Svensson
2021-01-31 22:46:15 +01:00
committed by Patrik Svensson
parent 58400fe74e
commit b64e016e8c
32 changed files with 911 additions and 41 deletions

View File

@ -40,6 +40,11 @@ namespace Spectre.Console
/// </summary>
public PanelHeader? Header { get; set; }
/// <summary>
/// Gets or sets a value indicating whether or not the panel is inlined.
/// </summary>
internal bool Inline { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="Panel"/> class.
/// </summary>
@ -71,29 +76,41 @@ namespace Spectre.Console
/// <inheritdoc/>
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
{
var edgeWidth = EdgeWidth;
var border = BoxExtensions.GetSafeBorder(Border, (context.LegacyConsole || !context.Unicode) && UseSafeBorder);
var borderStyle = BorderStyle ?? Style.Plain;
var showBorder = true;
if (border is NoBoxBorder)
{
showBorder = false;
edgeWidth = 0;
}
var child = new Padder(_child, Padding);
var childWidth = maxWidth - EdgeWidth;
var childWidth = maxWidth - edgeWidth;
if (!Expand)
{
var measurement = ((IRenderable)child).Measure(context, maxWidth - EdgeWidth);
var measurement = ((IRenderable)child).Measure(context, maxWidth - edgeWidth);
childWidth = measurement.Max;
}
var panelWidth = childWidth + EdgeWidth;
var panelWidth = childWidth + edgeWidth;
panelWidth = Math.Min(panelWidth, maxWidth);
var result = new List<Segment>();
// Panel top
AddTopBorder(result, context, border, borderStyle, panelWidth);
if (showBorder)
{
// Panel top
AddTopBorder(result, context, border, borderStyle, panelWidth);
}
// Split the child segments into lines.
var childSegments = ((IRenderable)child).Render(context, childWidth);
foreach (var line in Segment.SplitLines(context, childSegments, childWidth))
foreach (var (_, _, last, line) in Segment.SplitLines(context, childSegments, childWidth).Enumerate())
{
if (line.Count == 1 && line[0].IsWhiteSpace)
{
@ -102,7 +119,10 @@ namespace Spectre.Console
continue;
}
result.Add(new Segment(border.GetPart(BoxBorderPart.Left), borderStyle));
if (showBorder)
{
result.Add(new Segment(border.GetPart(BoxBorderPart.Left), borderStyle));
}
var content = new List<Segment>();
content.AddRange(line);
@ -117,20 +137,45 @@ namespace Spectre.Console
result.AddRange(content);
result.Add(new Segment(border.GetPart(BoxBorderPart.Right), borderStyle));
if (showBorder)
{
result.Add(new Segment(border.GetPart(BoxBorderPart.Right), borderStyle));
}
// Don't emit a line break if this is the last
// line, we're not showing the border, and we're
// not rendering this inline.
var emitLinebreak = !(last && !showBorder && !Inline);
if (!emitLinebreak)
{
continue;
}
result.Add(Segment.LineBreak);
}
// Panel bottom
result.Add(new Segment(border.GetPart(BoxBorderPart.BottomLeft), borderStyle));
result.Add(new Segment(border.GetPart(BoxBorderPart.Bottom).Repeat(panelWidth - EdgeWidth), borderStyle));
result.Add(new Segment(border.GetPart(BoxBorderPart.BottomRight), borderStyle));
result.Add(Segment.LineBreak);
if (showBorder)
{
result.Add(new Segment(border.GetPart(BoxBorderPart.BottomLeft), borderStyle));
result.Add(new Segment(border.GetPart(BoxBorderPart.Bottom).Repeat(panelWidth - EdgeWidth), borderStyle));
result.Add(new Segment(border.GetPart(BoxBorderPart.BottomRight), borderStyle));
}
// TODO: Need a better name for this?
// If we're rendering this as part of an inline parent renderable,
// such as columns, we should not emit the last line break.
if (!Inline)
{
result.Add(Segment.LineBreak);
}
return result;
}
private void AddTopBorder(List<Segment> result, RenderContext context, BoxBorder border, Style borderStyle, int panelWidth)
private void AddTopBorder(
List<Segment> result, RenderContext context, BoxBorder border,
Style borderStyle, int panelWidth)
{
var rule = new Rule
{