mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-16 00:42:51 +08:00
Restructure solution a bit
This commit is contained in:
parent
003e15686f
commit
4f06687104
@ -42,7 +42,7 @@
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.113">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.Analyzers" Version="2.3.0">
|
||||
<PackageReference Include="Roslynator.Analyzers" Version="3.0.0">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
@ -49,7 +49,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting"),
|
||||
Header = new PanelHeader("Greeting"),
|
||||
Expand = true,
|
||||
Padding = new Padding(2, 2),
|
||||
});
|
||||
@ -70,7 +70,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting").LeftAligned(),
|
||||
Header = new PanelHeader("Greeting").LeftAligned(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
@ -90,7 +90,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting").Centered(),
|
||||
Header = new PanelHeader("Greeting").Centered(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
@ -110,7 +110,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting").RightAligned(),
|
||||
Header = new PanelHeader("Greeting").RightAligned(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
@ -130,7 +130,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting"),
|
||||
Header = new PanelHeader("Greeting"),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IHasBorder"/>.
|
||||
/// </summary>
|
||||
public static class BorderExtensions
|
||||
public static class HasBorderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Do not display a border.
|
@ -27,7 +27,7 @@ namespace Spectre.Console
|
||||
throw new ArgumentNullException(nameof(text));
|
||||
}
|
||||
|
||||
return SetHeader(panel, new Header(text, style, alignment));
|
||||
return SetHeader(panel, new PanelHeader(text, style, alignment));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -36,7 +36,7 @@ namespace Spectre.Console
|
||||
/// <param name="panel">The panel.</param>
|
||||
/// <param name="header">The header to use.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static Panel SetHeader(this Panel panel, Header header)
|
||||
public static Panel SetHeader(this Panel panel, PanelHeader header)
|
||||
{
|
||||
if (panel is null)
|
||||
{
|
@ -266,8 +266,8 @@ namespace Spectre.Console.Rendering
|
||||
/// </summary>
|
||||
/// <param name="segment">The segment to split.</param>
|
||||
/// <param name="overflow">The overflow strategy to use.</param>
|
||||
/// <param name="encoding">The encodign to use.</param>
|
||||
/// <param name="width">The maxiumum width.</param>
|
||||
/// <param name="encoding">The encoding to use.</param>
|
||||
/// <param name="width">The maximum width.</param>
|
||||
/// <returns>A list of segments that has been split.</returns>
|
||||
public static List<Segment> SplitOverflow(Segment segment, Overflow? overflow, Encoding encoding, int width)
|
||||
{
|
||||
@ -317,7 +317,7 @@ namespace Spectre.Console.Rendering
|
||||
new Segment(text, style),
|
||||
Overflow.Ellipsis,
|
||||
encoding,
|
||||
maxWidth).First();
|
||||
maxWidth)[0];
|
||||
}
|
||||
|
||||
internal static List<List<SegmentLine>> MakeSameHeight(int cellHeight, List<List<SegmentLine>> cells)
|
||||
|
@ -3,20 +3,34 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
internal sealed class SegmentLineEnumerator : IEnumerable<Segment>
|
||||
/// <summary>
|
||||
/// An enumerator for <see cref="SegmentLine"/> collections.
|
||||
/// </summary>
|
||||
public sealed class SegmentLineEnumerator : IEnumerable<Segment>
|
||||
{
|
||||
private readonly List<SegmentLine> _lines;
|
||||
|
||||
public SegmentLineEnumerator(List<SegmentLine> lines)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SegmentLineEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="lines">The lines to enumerate.</param>
|
||||
public SegmentLineEnumerator(IEnumerable<SegmentLine> lines)
|
||||
{
|
||||
_lines = lines;
|
||||
if (lines is null)
|
||||
{
|
||||
throw new System.ArgumentNullException(nameof(lines));
|
||||
}
|
||||
|
||||
_lines = new List<SegmentLine>(lines);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<Segment> GetEnumerator()
|
||||
{
|
||||
return new SegmentLineIterator(_lines);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
|
@ -3,29 +3,48 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
internal sealed class SegmentLineIterator : IEnumerator<Segment>
|
||||
/// <summary>
|
||||
/// An iterator for <see cref="SegmentLine"/> collections.
|
||||
/// </summary>
|
||||
public sealed class SegmentLineIterator : IEnumerator<Segment>
|
||||
{
|
||||
private readonly List<SegmentLine> _lines;
|
||||
private int _currentLine;
|
||||
private int _currentIndex;
|
||||
private bool _lineBreakEmitted;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current segment.
|
||||
/// </summary>
|
||||
public Segment Current { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
object? IEnumerator.Current => Current;
|
||||
|
||||
public SegmentLineIterator(List<SegmentLine> lines)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SegmentLineIterator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="lines">The lines to iterate.</param>
|
||||
public SegmentLineIterator(IEnumerable<SegmentLine> lines)
|
||||
{
|
||||
if (lines is null)
|
||||
{
|
||||
throw new System.ArgumentNullException(nameof(lines));
|
||||
}
|
||||
|
||||
_currentLine = 0;
|
||||
_currentIndex = -1;
|
||||
_lines = lines;
|
||||
_lines = new List<SegmentLine>(lines);
|
||||
|
||||
Current = Segment.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_currentLine > _lines.Count - 1)
|
||||
@ -88,6 +107,7 @@ namespace Spectre.Console.Rendering
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Reset()
|
||||
{
|
||||
_currentLine = 0;
|
||||
|
@ -1,133 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Internal;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a table.
|
||||
/// </summary>
|
||||
public sealed partial class Table
|
||||
{
|
||||
private const int EdgeCount = 2;
|
||||
|
||||
// Calculate the widths of each column, including padding, not including borders.
|
||||
// Ported from Rich by Will McGugan, licensed under MIT.
|
||||
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L394
|
||||
private List<int> CalculateColumnWidths(RenderContext options, int maxWidth)
|
||||
{
|
||||
var width_ranges = _columns.Select(column => MeasureColumn(column, options, maxWidth)).ToArray();
|
||||
var widths = width_ranges.Select(range => range.Max).ToList();
|
||||
|
||||
var tableWidth = widths.Sum();
|
||||
|
||||
if (tableWidth > maxWidth)
|
||||
{
|
||||
var wrappable = _columns.Select(c => !c.NoWrap).ToList();
|
||||
widths = CollapseWidths(widths, wrappable, maxWidth);
|
||||
tableWidth = widths.Sum();
|
||||
|
||||
// last resort, reduce columns evenly
|
||||
if (tableWidth > maxWidth)
|
||||
{
|
||||
var excessWidth = tableWidth - maxWidth;
|
||||
widths = Ratio.Reduce(excessWidth, widths.Select(_ => 1).ToList(), widths, widths);
|
||||
tableWidth = widths.Sum();
|
||||
}
|
||||
}
|
||||
|
||||
if (tableWidth < maxWidth && ShouldExpand())
|
||||
{
|
||||
var padWidths = Ratio.Distribute(maxWidth - tableWidth, widths);
|
||||
widths = widths.Zip(padWidths, (a, b) => (a, b)).Select(f => f.a + f.b).ToList();
|
||||
}
|
||||
|
||||
return widths;
|
||||
}
|
||||
|
||||
// Reduce widths so that the total is less or equal to the max width.
|
||||
// Ported from Rich by Will McGugan, licensed under MIT.
|
||||
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L442
|
||||
private static List<int> CollapseWidths(List<int> widths, List<bool> wrappable, int maxWidth)
|
||||
{
|
||||
var totalWidth = widths.Sum();
|
||||
var excessWidth = totalWidth - maxWidth;
|
||||
|
||||
if (wrappable.AnyTrue())
|
||||
{
|
||||
while (totalWidth != 0 && excessWidth > 0)
|
||||
{
|
||||
var maxColumn = widths.Zip(wrappable, (first, second) => (width: first, allowWrap: second))
|
||||
.Where(x => x.allowWrap)
|
||||
.Max(x => x.width);
|
||||
|
||||
var secondMaxColumn = widths.Zip(wrappable, (width, allowWrap) => allowWrap && width != maxColumn ? width : 1).Max();
|
||||
var columnDifference = maxColumn - secondMaxColumn;
|
||||
|
||||
var ratios = widths.Zip(wrappable, (width, allowWrap) => width == maxColumn && allowWrap ? 1 : 0).ToList();
|
||||
if (!ratios.Any(x => x != 0) || columnDifference == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var maxReduce = widths.Select(_ => Math.Min(excessWidth, columnDifference)).ToList();
|
||||
widths = Ratio.Reduce(excessWidth, ratios, maxReduce, widths);
|
||||
|
||||
totalWidth = widths.Sum();
|
||||
excessWidth = totalWidth - maxWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return widths;
|
||||
}
|
||||
|
||||
private (int Min, int Max) MeasureColumn(TableColumn column, RenderContext options, int maxWidth)
|
||||
{
|
||||
var padding = column.Padding.GetHorizontalPadding();
|
||||
|
||||
// Predetermined width?
|
||||
if (column.Width != null)
|
||||
{
|
||||
return (column.Width.Value + padding, column.Width.Value + padding);
|
||||
}
|
||||
|
||||
var columnIndex = _columns.IndexOf(column);
|
||||
var rows = _rows.Select(row => row[columnIndex]);
|
||||
|
||||
var minWidths = new List<int>();
|
||||
var maxWidths = new List<int>();
|
||||
|
||||
// Include columns in measurement
|
||||
var measure = column.Text.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
measure = row.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
}
|
||||
|
||||
return (minWidths.Count > 0 ? minWidths.Max() : padding,
|
||||
maxWidths.Count > 0 ? maxWidths.Max() : maxWidth);
|
||||
}
|
||||
|
||||
private int GetExtraWidth(bool includePadding)
|
||||
{
|
||||
var hideBorder = !Border.Visible;
|
||||
var separators = hideBorder ? 0 : _columns.Count - 1;
|
||||
var edges = hideBorder ? 0 : EdgeCount;
|
||||
var padding = includePadding ? _columns.Select(x => x.Padding.GetHorizontalPadding()).Sum() : 0;
|
||||
|
||||
if (!PadRightCell)
|
||||
{
|
||||
padding -= _columns.Last().Padding.Right;
|
||||
}
|
||||
|
||||
return separators + edges + padding;
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,18 @@
|
||||
<None Include="../../resources/gfx/small-logo.png" Pack="true" PackagePath="\" Link="Properties/small-logo.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="AnsiConsole.*.cs">
|
||||
<DependentUpon>AnsiConsole.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Color.*.cs">
|
||||
<DependentUpon>Color.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Border.*.cs">
|
||||
<DependentUpon>Border.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TunnelVisionLabs.ReferenceAssemblyAnnotator" Version="1.0.0-alpha.160" PrivateAssets="all" />
|
||||
<PackageDownload Include="Microsoft.NETCore.App.Ref" Version="[$(AnnotatedReferenceAssemblyVersion)]" />
|
||||
|
@ -1,40 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents color and text decoration.
|
||||
/// </summary>
|
||||
public sealed partial class Style : IEquatable<Style>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified foreground color.
|
||||
/// </summary>
|
||||
/// <param name="color">The foreground color.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified foreground color.</returns>
|
||||
public static Style WithForeground(Color color)
|
||||
{
|
||||
return new Style(foreground: color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified background color.
|
||||
/// </summary>
|
||||
/// <param name="color">The background color.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified background color.</returns>
|
||||
public static Style WithBackground(Color color)
|
||||
{
|
||||
return new Style(background: color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified text decoration.
|
||||
/// </summary>
|
||||
/// <param name="decoration">The text decoration.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified text decoration.</returns>
|
||||
public static Style WithDecoration(Decoration decoration)
|
||||
{
|
||||
return new Style(decoration: decoration);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Represents color and text decoration.
|
||||
/// </summary>
|
||||
public sealed partial class Style : IEquatable<Style>
|
||||
public sealed class Style : IEquatable<Style>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the foreground color.
|
||||
@ -48,6 +48,36 @@ namespace Spectre.Console
|
||||
Decoration = decoration ?? Decoration.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified foreground color.
|
||||
/// </summary>
|
||||
/// <param name="color">The foreground color.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified foreground color.</returns>
|
||||
public static Style WithForeground(Color color)
|
||||
{
|
||||
return new Style(foreground: color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified background color.
|
||||
/// </summary>
|
||||
/// <param name="color">The background color.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified background color.</returns>
|
||||
public static Style WithBackground(Color color)
|
||||
{
|
||||
return new Style(background: color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified text decoration.
|
||||
/// </summary>
|
||||
/// <param name="decoration">The text decoration.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified text decoration.</returns>
|
||||
public static Style WithDecoration(Decoration decoration)
|
||||
{
|
||||
return new Style(decoration: decoration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a copy of the current <see cref="Style"/>.
|
||||
/// </summary>
|
||||
|
@ -38,7 +38,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Gets or sets the header.
|
||||
/// </summary>
|
||||
public Header? Header { get; set; }
|
||||
public PanelHeader? Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Panel"/> class.
|
@ -5,7 +5,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Represents a header.
|
||||
/// </summary>
|
||||
public sealed class Header : IAlignable
|
||||
public sealed class PanelHeader : IAlignable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the header text.
|
||||
@ -23,12 +23,12 @@ namespace Spectre.Console
|
||||
public Justify? Alignment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Header"/> class.
|
||||
/// Initializes a new instance of the <see cref="PanelHeader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="text">The header text.</param>
|
||||
/// <param name="style">The header style.</param>
|
||||
/// <param name="alignment">The header alignment.</param>
|
||||
public Header(string text, Style? style = null, Justify? alignment = null)
|
||||
public PanelHeader(string text, Style? style = null, Justify? alignment = null)
|
||||
{
|
||||
Text = text ?? throw new ArgumentNullException(nameof(text));
|
||||
Style = style;
|
||||
@ -40,7 +40,7 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
/// <param name="style">The header style.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public Header SetStyle(Style? style)
|
||||
public PanelHeader SetStyle(Style? style)
|
||||
{
|
||||
Style = style ?? Style.Plain;
|
||||
return this;
|
||||
@ -51,7 +51,7 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
/// <param name="alignment">The header alignment.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public Header SetAlignment(Justify alignment)
|
||||
public PanelHeader SetAlignment(Justify alignment)
|
||||
{
|
||||
Alignment = alignment;
|
||||
return this;
|
@ -9,8 +9,10 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// A renderable table.
|
||||
/// </summary>
|
||||
public sealed partial class Table : Renderable, IHasBorder, IExpandable
|
||||
public sealed class Table : Renderable, IHasBorder, IExpandable
|
||||
{
|
||||
private const int EdgeCount = 2;
|
||||
|
||||
private readonly List<TableColumn> _columns;
|
||||
private readonly List<List<IRenderable>> _rows;
|
||||
|
||||
@ -329,6 +331,123 @@ namespace Spectre.Console
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate the widths of each column, including padding, not including borders.
|
||||
// Ported from Rich by Will McGugan, licensed under MIT.
|
||||
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L394
|
||||
private List<int> CalculateColumnWidths(RenderContext options, int maxWidth)
|
||||
{
|
||||
var width_ranges = _columns.Select(column => MeasureColumn(column, options, maxWidth)).ToArray();
|
||||
var widths = width_ranges.Select(range => range.Max).ToList();
|
||||
|
||||
var tableWidth = widths.Sum();
|
||||
|
||||
if (tableWidth > maxWidth)
|
||||
{
|
||||
var wrappable = _columns.Select(c => !c.NoWrap).ToList();
|
||||
widths = CollapseWidths(widths, wrappable, maxWidth);
|
||||
tableWidth = widths.Sum();
|
||||
|
||||
// last resort, reduce columns evenly
|
||||
if (tableWidth > maxWidth)
|
||||
{
|
||||
var excessWidth = tableWidth - maxWidth;
|
||||
widths = Ratio.Reduce(excessWidth, widths.Select(_ => 1).ToList(), widths, widths);
|
||||
tableWidth = widths.Sum();
|
||||
}
|
||||
}
|
||||
|
||||
if (tableWidth < maxWidth && ShouldExpand())
|
||||
{
|
||||
var padWidths = Ratio.Distribute(maxWidth - tableWidth, widths);
|
||||
widths = widths.Zip(padWidths, (a, b) => (a, b)).Select(f => f.a + f.b).ToList();
|
||||
}
|
||||
|
||||
return widths;
|
||||
}
|
||||
|
||||
// Reduce widths so that the total is less or equal to the max width.
|
||||
// Ported from Rich by Will McGugan, licensed under MIT.
|
||||
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L442
|
||||
private static List<int> CollapseWidths(List<int> widths, List<bool> wrappable, int maxWidth)
|
||||
{
|
||||
var totalWidth = widths.Sum();
|
||||
var excessWidth = totalWidth - maxWidth;
|
||||
|
||||
if (wrappable.AnyTrue())
|
||||
{
|
||||
while (totalWidth != 0 && excessWidth > 0)
|
||||
{
|
||||
var maxColumn = widths.Zip(wrappable, (first, second) => (width: first, allowWrap: second))
|
||||
.Where(x => x.allowWrap)
|
||||
.Max(x => x.width);
|
||||
|
||||
var secondMaxColumn = widths.Zip(wrappable, (width, allowWrap) => allowWrap && width != maxColumn ? width : 1).Max();
|
||||
var columnDifference = maxColumn - secondMaxColumn;
|
||||
|
||||
var ratios = widths.Zip(wrappable, (width, allowWrap) => width == maxColumn && allowWrap ? 1 : 0).ToList();
|
||||
if (!ratios.Any(x => x != 0) || columnDifference == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var maxReduce = widths.Select(_ => Math.Min(excessWidth, columnDifference)).ToList();
|
||||
widths = Ratio.Reduce(excessWidth, ratios, maxReduce, widths);
|
||||
|
||||
totalWidth = widths.Sum();
|
||||
excessWidth = totalWidth - maxWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return widths;
|
||||
}
|
||||
|
||||
private (int Min, int Max) MeasureColumn(TableColumn column, RenderContext options, int maxWidth)
|
||||
{
|
||||
var padding = column.Padding.GetHorizontalPadding();
|
||||
|
||||
// Predetermined width?
|
||||
if (column.Width != null)
|
||||
{
|
||||
return (column.Width.Value + padding, column.Width.Value + padding);
|
||||
}
|
||||
|
||||
var columnIndex = _columns.IndexOf(column);
|
||||
var rows = _rows.Select(row => row[columnIndex]);
|
||||
|
||||
var minWidths = new List<int>();
|
||||
var maxWidths = new List<int>();
|
||||
|
||||
// Include columns in measurement
|
||||
var measure = column.Text.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
measure = row.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
}
|
||||
|
||||
return (minWidths.Count > 0 ? minWidths.Max() : padding,
|
||||
maxWidths.Count > 0 ? maxWidths.Max() : maxWidth);
|
||||
}
|
||||
|
||||
private int GetExtraWidth(bool includePadding)
|
||||
{
|
||||
var hideBorder = !Border.Visible;
|
||||
var separators = hideBorder ? 0 : _columns.Count - 1;
|
||||
var edges = hideBorder ? 0 : EdgeCount;
|
||||
var padding = includePadding ? _columns.Select(x => x.Padding.GetHorizontalPadding()).Sum() : 0;
|
||||
|
||||
if (!PadRightCell)
|
||||
{
|
||||
padding -= _columns.Last().Padding.Right;
|
||||
}
|
||||
|
||||
return separators + edges + padding;
|
||||
}
|
||||
|
||||
private bool ShouldExpand()
|
||||
{
|
||||
return Expand || Width != null;
|
Loading…
x
Reference in New Issue
Block a user