mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-07-04 11:48:16 +08:00
Use file scoped namespace declarations
This commit is contained in:

committed by
Phil Scott

parent
1dbaf50935
commit
ec1188b837
@ -3,200 +3,199 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
namespace Spectre.Console;
|
||||
|
||||
/// <summary>
|
||||
/// A renderable panel.
|
||||
/// </summary>
|
||||
public sealed class Panel : Renderable, IHasBoxBorder, IHasBorder, IExpandable, IPaddable
|
||||
{
|
||||
private const int EdgeWidth = 2;
|
||||
|
||||
private readonly IRenderable _child;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BoxBorder Border { get; set; } = BoxBorder.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool UseSafeBorder { get; set; } = true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Style? BorderStyle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A renderable panel.
|
||||
/// Gets or sets a value indicating whether or not the panel should
|
||||
/// fit the available space. If <c>false</c>, the panel width will be
|
||||
/// auto calculated. Defaults to <c>false</c>.
|
||||
/// </summary>
|
||||
public sealed class Panel : Renderable, IHasBoxBorder, IHasBorder, IExpandable, IPaddable
|
||||
public bool Expand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the padding.
|
||||
/// </summary>
|
||||
public Padding? Padding { get; set; } = new Padding(1, 0, 1, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the header.
|
||||
/// </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>
|
||||
/// <param name="text">The panel content.</param>
|
||||
public Panel(string text)
|
||||
: this(new Markup(text))
|
||||
{
|
||||
private const int EdgeWidth = 2;
|
||||
}
|
||||
|
||||
private readonly IRenderable _child;
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Panel"/> class.
|
||||
/// </summary>
|
||||
/// <param name="content">The panel content.</param>
|
||||
public Panel(IRenderable content)
|
||||
{
|
||||
_child = content ?? throw new ArgumentNullException(nameof(content));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BoxBorder Border { get; set; } = BoxBorder.Square;
|
||||
/// <inheritdoc/>
|
||||
protected override Measurement Measure(RenderContext context, int maxWidth)
|
||||
{
|
||||
var child = new Padder(_child, Padding);
|
||||
var childWidth = ((IRenderable)child).Measure(context, maxWidth);
|
||||
return new Measurement(
|
||||
childWidth.Min + EdgeWidth,
|
||||
childWidth.Max + EdgeWidth);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool UseSafeBorder { get; set; } = true;
|
||||
/// <inheritdoc/>
|
||||
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
|
||||
{
|
||||
var edgeWidth = EdgeWidth;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Style? BorderStyle { get; set; }
|
||||
var border = BoxExtensions.GetSafeBorder(Border, !context.Unicode && UseSafeBorder);
|
||||
var borderStyle = BorderStyle ?? Style.Plain;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not the panel should
|
||||
/// fit the available space. If <c>false</c>, the panel width will be
|
||||
/// auto calculated. Defaults to <c>false</c>.
|
||||
/// </summary>
|
||||
public bool Expand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the padding.
|
||||
/// </summary>
|
||||
public Padding? Padding { get; set; } = new Padding(1, 0, 1, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the header.
|
||||
/// </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>
|
||||
/// <param name="text">The panel content.</param>
|
||||
public Panel(string text)
|
||||
: this(new Markup(text))
|
||||
var showBorder = true;
|
||||
if (border is NoBoxBorder)
|
||||
{
|
||||
showBorder = false;
|
||||
edgeWidth = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Panel"/> class.
|
||||
/// </summary>
|
||||
/// <param name="content">The panel content.</param>
|
||||
public Panel(IRenderable content)
|
||||
var child = new Padder(_child, Padding);
|
||||
var childWidth = maxWidth - edgeWidth;
|
||||
|
||||
if (!Expand)
|
||||
{
|
||||
_child = content ?? throw new ArgumentNullException(nameof(content));
|
||||
var measurement = ((IRenderable)child).Measure(context, maxWidth - edgeWidth);
|
||||
childWidth = measurement.Max;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Measurement Measure(RenderContext context, int maxWidth)
|
||||
var panelWidth = childWidth + edgeWidth;
|
||||
panelWidth = Math.Min(panelWidth, maxWidth);
|
||||
childWidth = panelWidth - edgeWidth;
|
||||
|
||||
var result = new List<Segment>();
|
||||
|
||||
if (showBorder)
|
||||
{
|
||||
var child = new Padder(_child, Padding);
|
||||
var childWidth = ((IRenderable)child).Measure(context, maxWidth);
|
||||
return new Measurement(
|
||||
childWidth.Min + EdgeWidth,
|
||||
childWidth.Max + EdgeWidth);
|
||||
// Panel top
|
||||
AddTopBorder(result, context, border, borderStyle, panelWidth);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
|
||||
// Split the child segments into lines.
|
||||
var childSegments = ((IRenderable)child).Render(context, childWidth);
|
||||
foreach (var (_, _, last, line) in Segment.SplitLines(childSegments, childWidth).Enumerate())
|
||||
{
|
||||
var edgeWidth = EdgeWidth;
|
||||
|
||||
var border = BoxExtensions.GetSafeBorder(Border, !context.Unicode && UseSafeBorder);
|
||||
var borderStyle = BorderStyle ?? Style.Plain;
|
||||
|
||||
var showBorder = true;
|
||||
if (border is NoBoxBorder)
|
||||
if (line.Count == 1 && line[0].IsWhiteSpace)
|
||||
{
|
||||
showBorder = false;
|
||||
edgeWidth = 0;
|
||||
// NOTE: This check might impact other things.
|
||||
// Hopefully not, but there is a chance.
|
||||
continue;
|
||||
}
|
||||
|
||||
var child = new Padder(_child, Padding);
|
||||
var childWidth = maxWidth - edgeWidth;
|
||||
|
||||
if (!Expand)
|
||||
{
|
||||
var measurement = ((IRenderable)child).Measure(context, maxWidth - edgeWidth);
|
||||
childWidth = measurement.Max;
|
||||
}
|
||||
|
||||
var panelWidth = childWidth + edgeWidth;
|
||||
panelWidth = Math.Min(panelWidth, maxWidth);
|
||||
childWidth = panelWidth - edgeWidth;
|
||||
|
||||
var result = new List<Segment>();
|
||||
|
||||
if (showBorder)
|
||||
{
|
||||
// Panel top
|
||||
AddTopBorder(result, context, border, borderStyle, panelWidth);
|
||||
result.Add(new Segment(border.GetPart(BoxBorderPart.Left), borderStyle));
|
||||
}
|
||||
|
||||
// Split the child segments into lines.
|
||||
var childSegments = ((IRenderable)child).Render(context, childWidth);
|
||||
foreach (var (_, _, last, line) in Segment.SplitLines(childSegments, childWidth).Enumerate())
|
||||
var content = new List<Segment>();
|
||||
content.AddRange(line);
|
||||
|
||||
// Do we need to pad the panel?
|
||||
var length = line.Sum(segment => segment.CellCount());
|
||||
if (length < childWidth)
|
||||
{
|
||||
if (line.Count == 1 && line[0].IsWhiteSpace)
|
||||
{
|
||||
// NOTE: This check might impact other things.
|
||||
// Hopefully not, but there is a chance.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (showBorder)
|
||||
{
|
||||
result.Add(new Segment(border.GetPart(BoxBorderPart.Left), borderStyle));
|
||||
}
|
||||
|
||||
var content = new List<Segment>();
|
||||
content.AddRange(line);
|
||||
|
||||
// Do we need to pad the panel?
|
||||
var length = line.Sum(segment => segment.CellCount());
|
||||
if (length < childWidth)
|
||||
{
|
||||
var diff = childWidth - length;
|
||||
content.Add(Segment.Padding(diff));
|
||||
}
|
||||
|
||||
result.AddRange(content);
|
||||
|
||||
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);
|
||||
var diff = childWidth - length;
|
||||
content.Add(Segment.Padding(diff));
|
||||
}
|
||||
|
||||
// Panel bottom
|
||||
result.AddRange(content);
|
||||
|
||||
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));
|
||||
result.Add(new Segment(border.GetPart(BoxBorderPart.Right), 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)
|
||||
// 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)
|
||||
{
|
||||
result.Add(Segment.LineBreak);
|
||||
continue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void AddTopBorder(
|
||||
List<Segment> result, RenderContext context, BoxBorder border,
|
||||
Style borderStyle, int panelWidth)
|
||||
{
|
||||
var rule = new Rule
|
||||
{
|
||||
Style = borderStyle,
|
||||
Border = border,
|
||||
TitlePadding = 1,
|
||||
TitleSpacing = 0,
|
||||
Title = Header?.Text,
|
||||
Alignment = Header?.Alignment ?? Justify.Left,
|
||||
};
|
||||
|
||||
// Top left border
|
||||
result.Add(new Segment(border.GetPart(BoxBorderPart.TopLeft), borderStyle));
|
||||
|
||||
// Top border (and header text if specified)
|
||||
result.AddRange(((IRenderable)rule).Render(context, panelWidth - 2).Where(x => !x.IsLineBreak));
|
||||
|
||||
// Top right border
|
||||
result.Add(new Segment(border.GetPart(BoxBorderPart.TopRight), borderStyle));
|
||||
result.Add(Segment.LineBreak);
|
||||
}
|
||||
|
||||
// Panel bottom
|
||||
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)
|
||||
{
|
||||
var rule = new Rule
|
||||
{
|
||||
Style = borderStyle,
|
||||
Border = border,
|
||||
TitlePadding = 1,
|
||||
TitleSpacing = 0,
|
||||
Title = Header?.Text,
|
||||
Alignment = Header?.Alignment ?? Justify.Left,
|
||||
};
|
||||
|
||||
// Top left border
|
||||
result.Add(new Segment(border.GetPart(BoxBorderPart.TopLeft), borderStyle));
|
||||
|
||||
// Top border (and header text if specified)
|
||||
result.AddRange(((IRenderable)rule).Render(context, panelWidth - 2).Where(x => !x.IsLineBreak));
|
||||
|
||||
// Top right border
|
||||
result.Add(new Segment(border.GetPart(BoxBorderPart.TopRight), borderStyle));
|
||||
result.Add(Segment.LineBreak);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user