/// <inheritdoc/> protected override IEnumerable <Segment> Render(RenderContext context, int maxWidth) { if (context is null) { throw new ArgumentNullException(nameof(context)); } if (_lines.Count == 0) { return(Array.Empty <Segment>()); } var lines = context.SingleLine ? new List <SegmentLine>(_lines) : SplitLines(maxWidth); // Justify lines var justification = context.Justification ?? Alignment ?? Justify.Left; if (justification != Justify.Left) { foreach (var line in lines) { Aligner.Align(context, line, justification, maxWidth); } } if (context.SingleLine) { // Return the first line return(lines[0].Where(segment => !segment.IsLineBreak)); } return(new SegmentLineEnumerator(lines)); }
private static IEnumerable <Segment> RenderAnnotation(TableRendererContext context, TableTitle?header, Style defaultStyle) { if (header == null) { return(Array.Empty <Segment>()); } var paragraph = new Markup(header.Text.Capitalize(), header.Style ?? defaultStyle) .Alignment(Justify.Center) .Overflow(Overflow.Ellipsis); // Render the paragraphs var segments = new List <Segment>(); segments.AddRange(((IRenderable)paragraph).Render(context.Options, context.TableWidth)); // Align over the whole buffer area Aligner.Align(context.Options, segments, context.Alignment, context.MaxWidth); segments.Add(Segment.LineBreak); return(segments); }
private IEnumerable <Segment> RenderAnnotation( RenderContext context, TableTitle?header, int maxWidth, int tableWidth, Style defaultStyle) { if (header == null) { return(Array.Empty <Segment>()); } var paragraph = new Markup(header.Text.Capitalize(), header.Style ?? defaultStyle) .Alignment(Justify.Center) .Overflow(Overflow.Ellipsis); var items = new List <Segment>(); items.AddRange(((IRenderable)paragraph).Render(context, tableWidth)); // Align over the whole buffer area Aligner.Align(context, items, Alignment, maxWidth); items.Add(Segment.LineBreak); return(items); }
/// <inheritdoc/> protected override IEnumerable <Segment> Render(RenderContext context, int maxWidth) { if (context is null) { throw new ArgumentNullException(nameof(context)); } var border = Border.GetSafeBorder((context.LegacyConsole || !context.Unicode) && UseSafeBorder); var borderStyle = BorderStyle ?? Style.Plain; var tableWidth = maxWidth; var actualMaxWidth = maxWidth; var showBorder = Border.Visible; var hideBorder = !Border.Visible; var hasRows = _rows.Count > 0; var hasFooters = _columns.Any(c => c.Footer != null); if (Width != null) { maxWidth = Math.Min(Width.Value, maxWidth); } maxWidth -= GetExtraWidth(includePadding: true); // Calculate the column and table widths var columnWidths = CalculateColumnWidths(context, maxWidth); // Update the table width. tableWidth = columnWidths.Sum() + GetExtraWidth(includePadding: true); if (tableWidth <= 0 || tableWidth > actualMaxWidth || columnWidths.Any(c => c <= 0)) { return(new List <Segment>(new[] { new Segment("…", BorderStyle ?? Style.Plain) })); } var rows = new List <TableRow>(); if (ShowHeaders) { // Add columns to top of rows rows.Add(new TableRow(new List <IRenderable>(_columns.Select(c => c.Header)))); } // Add rows. rows.AddRange(_rows); if (hasFooters) { rows.Add(new TableRow(new List <IRenderable>(_columns.Select(c => c.Footer ?? Text.Empty)))); } var result = new List <Segment>(); result.AddRange(RenderAnnotation(context, Title, actualMaxWidth, tableWidth, _defaultHeadingStyle)); // Iterate all rows foreach (var(index, firstRow, lastRow, row) in rows.Enumerate()) { var cellHeight = 1; // Get the list of cells for the row and calculate the cell height var cells = new List <List <SegmentLine> >(); foreach (var(columnIndex, _, _, (rowWidth, cell)) in columnWidths.Zip(row).Enumerate()) { var justification = _columns[columnIndex].Alignment; var childContext = context.WithJustification(justification); var lines = Segment.SplitLines(context, cell.Render(childContext, rowWidth)); cellHeight = Math.Max(cellHeight, lines.Count); cells.Add(lines); } // Show top of header? if (firstRow && showBorder) { var separator = Aligner.Align(context, border.GetColumnRow(TablePart.Top, columnWidths, _columns), Alignment, actualMaxWidth); result.Add(new Segment(separator, borderStyle)); result.Add(Segment.LineBreak); } // Show footer separator? if (ShowFooters && lastRow && showBorder && hasFooters) { var textBorder = border.GetColumnRow(TablePart.FooterSeparator, columnWidths, _columns); if (!string.IsNullOrEmpty(textBorder)) { var separator = Aligner.Align(context, textBorder, Alignment, actualMaxWidth); result.Add(new Segment(separator, borderStyle)); result.Add(Segment.LineBreak); } } // Make cells the same shape cells = Segment.MakeSameHeight(cellHeight, cells); // Iterate through each cell row foreach (var cellRowIndex in Enumerable.Range(0, cellHeight)) { var rowResult = new List <Segment>(); foreach (var(cellIndex, firstCell, lastCell, cell) in cells.Enumerate()) { if (firstCell && showBorder) { // Show left column edge var part = firstRow && ShowHeaders ? TableBorderPart.HeaderLeft : TableBorderPart.CellLeft; rowResult.Add(new Segment(border.GetPart(part), borderStyle)); } // Pad column on left side. if (showBorder || IsGrid) { var leftPadding = _columns[cellIndex].Padding.GetLeftSafe(); if (leftPadding > 0) { rowResult.Add(new Segment(new string(' ', leftPadding))); } } // Add content rowResult.AddRange(cell[cellRowIndex]); // Pad cell content right var length = cell[cellRowIndex].Sum(segment => segment.CellCount(context)); if (length < columnWidths[cellIndex]) { rowResult.Add(new Segment(new string(' ', columnWidths[cellIndex] - length))); } // Pad column on the right side if (showBorder || (hideBorder && !lastCell) || (hideBorder && lastCell && IsGrid && PadRightCell)) { var rightPadding = _columns[cellIndex].Padding.GetRightSafe(); if (rightPadding > 0) { rowResult.Add(new Segment(new string(' ', rightPadding))); } } if (lastCell && showBorder) { // Add right column edge var part = firstRow && ShowHeaders ? TableBorderPart.HeaderRight : TableBorderPart.CellRight; rowResult.Add(new Segment(border.GetPart(part), borderStyle)); } else if (showBorder) { // Add column separator var part = firstRow && ShowHeaders ? TableBorderPart.HeaderSeparator : TableBorderPart.CellSeparator; rowResult.Add(new Segment(border.GetPart(part), borderStyle)); } } // Align the row result. Aligner.Align(context, rowResult, Alignment, actualMaxWidth); // Is the row larger than the allowed max width? if (Segment.CellCount(context, rowResult) > actualMaxWidth) { result.AddRange(Segment.Truncate(context, rowResult, actualMaxWidth)); } else { result.AddRange(rowResult); } result.Add(Segment.LineBreak); } // Show header separator? if (firstRow && showBorder && ShowHeaders && hasRows) { var separator = Aligner.Align(context, border.GetColumnRow(TablePart.HeaderSeparator, columnWidths, _columns), Alignment, actualMaxWidth); result.Add(new Segment(separator, borderStyle)); result.Add(Segment.LineBreak); } // Show bottom of footer? if (lastRow && showBorder) { var separator = Aligner.Align(context, border.GetColumnRow(TablePart.Bottom, columnWidths, _columns), Alignment, actualMaxWidth); result.Add(new Segment(separator, borderStyle)); result.Add(Segment.LineBreak); } } result.AddRange(RenderAnnotation(context, Caption, actualMaxWidth, tableWidth, _defaultCaptionStyle)); return(result); }
public static List <Segment> Render(TableRendererContext context, List <int> columnWidths) { // Can't render the table? if (context.TableWidth <= 0 || context.TableWidth > context.MaxWidth || columnWidths.Any(c => c <= 0)) { return(new List <Segment>(new[] { new Segment("…", context.BorderStyle ?? Style.Plain) })); } var result = new List <Segment>(); result.AddRange(RenderAnnotation(context, context.Title, _defaultHeadingStyle)); // Iterate all rows foreach (var(index, isFirstRow, isLastRow, row) in context.Rows.Enumerate()) { var cellHeight = 1; // Get the list of cells for the row and calculate the cell height var cells = new List <List <SegmentLine> >(); foreach (var(columnIndex, _, _, (rowWidth, cell)) in columnWidths.Zip(row).Enumerate()) { var justification = context.Columns[columnIndex].Alignment; var childContext = context.Options.WithJustification(justification); var lines = Segment.SplitLines(context.Options, cell.Render(childContext, rowWidth)); cellHeight = Math.Max(cellHeight, lines.Count); cells.Add(lines); } // Show top of header? if (isFirstRow && context.ShowBorder) { var separator = Aligner.Align(context.Options, context.Border.GetColumnRow(TablePart.Top, columnWidths, context.Columns), context.Alignment, context.MaxWidth); result.Add(new Segment(separator, context.BorderStyle)); result.Add(Segment.LineBreak); } // Show footer separator? if (context.ShowFooters && isLastRow && context.ShowBorder && context.HasFooters) { var textBorder = context.Border.GetColumnRow(TablePart.FooterSeparator, columnWidths, context.Columns); if (!string.IsNullOrEmpty(textBorder)) { var separator = Aligner.Align(context.Options, textBorder, context.Alignment, context.MaxWidth); result.Add(new Segment(separator, context.BorderStyle)); result.Add(Segment.LineBreak); } } // Make cells the same shape cells = Segment.MakeSameHeight(cellHeight, cells); // Iterate through each cell row foreach (var cellRowIndex in Enumerable.Range(0, cellHeight)) { var rowResult = new List <Segment>(); foreach (var(cellIndex, isFirstCell, isLastCell, cell) in cells.Enumerate()) { if (isFirstCell && context.ShowBorder) { // Show left column edge var part = isFirstRow && context.ShowHeaders ? TableBorderPart.HeaderLeft : TableBorderPart.CellLeft; rowResult.Add(new Segment(context.Border.GetPart(part), context.BorderStyle)); } // Pad column on left side. if (context.ShowBorder || context.IsGrid) { var leftPadding = context.Columns[cellIndex].Padding.GetLeftSafe(); if (leftPadding > 0) { rowResult.Add(new Segment(new string(' ', leftPadding))); } } // Add content rowResult.AddRange(cell[cellRowIndex]); // Pad cell content right var length = cell[cellRowIndex].Sum(segment => segment.CellCount(context.Options)); if (length < columnWidths[cellIndex]) { rowResult.Add(new Segment(new string(' ', columnWidths[cellIndex] - length))); } // Pad column on the right side if (context.ShowBorder || (context.HideBorder && !isLastCell) || (context.HideBorder && isLastCell && context.IsGrid && context.PadRightCell)) { var rightPadding = context.Columns[cellIndex].Padding.GetRightSafe(); if (rightPadding > 0) { rowResult.Add(new Segment(new string(' ', rightPadding))); } } if (isLastCell && context.ShowBorder) { // Add right column edge var part = isFirstRow && context.ShowHeaders ? TableBorderPart.HeaderRight : TableBorderPart.CellRight; rowResult.Add(new Segment(context.Border.GetPart(part), context.BorderStyle)); } else if (context.ShowBorder) { // Add column separator var part = isFirstRow && context.ShowHeaders ? TableBorderPart.HeaderSeparator : TableBorderPart.CellSeparator; rowResult.Add(new Segment(context.Border.GetPart(part), context.BorderStyle)); } } // Align the row result. Aligner.Align(context.Options, rowResult, context.Alignment, context.MaxWidth); // Is the row larger than the allowed max width? if (Segment.CellCount(context.Options, rowResult) > context.MaxWidth) { result.AddRange(Segment.Truncate(context.Options, rowResult, context.MaxWidth)); } else { result.AddRange(rowResult); } result.Add(Segment.LineBreak); } // Show header separator? if (isFirstRow && context.ShowBorder && context.ShowHeaders && context.HasRows) { var separator = Aligner.Align(context.Options, context.Border.GetColumnRow(TablePart.HeaderSeparator, columnWidths, context.Columns), context.Alignment, context.MaxWidth); result.Add(new Segment(separator, context.BorderStyle)); result.Add(Segment.LineBreak); } // Show bottom of footer? if (isLastRow && context.ShowBorder) { var separator = Aligner.Align(context.Options, context.Border.GetColumnRow(TablePart.Bottom, columnWidths, context.Columns), context.Alignment, context.MaxWidth); result.Add(new Segment(separator, context.BorderStyle)); result.Add(Segment.LineBreak); } } result.AddRange(RenderAnnotation(context, context.Caption, _defaultCaptionStyle)); return(result); }