From ed73c5b82dbaf077f609562864963481355525f7 Mon Sep 17 00:00:00 2001 From: MarcinZiabek Date: Thu, 30 Dec 2021 19:42:40 +0100 Subject: [PATCH] Table: layouting improvements for paging --- QuestPDF.Examples/TableExamples.cs | 6 +-- QuestPDF/Drawing/SpacePlan.cs | 2 +- QuestPDF/Elements/Table/Table.cs | 85 ++++++++++++++++-------------- 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/QuestPDF.Examples/TableExamples.cs b/QuestPDF.Examples/TableExamples.cs index 9d952b9..3d23a9e 100644 --- a/QuestPDF.Examples/TableExamples.cs +++ b/QuestPDF.Examples/TableExamples.cs @@ -117,17 +117,17 @@ namespace QuestPDF.Examples .EnableCaching() .EnableDebugging(false) .ShowResults() - .Render(container => GeneratePerformanceStructure(container, 2500)); + .Render(container => GeneratePerformanceStructure(container, 250)); } public static void GeneratePerformanceStructure(IContainer container, int repeats) { container .Padding(25) - .Background(Colors.Blue.Lighten2) + //.Background(Colors.Blue.Lighten2) .Box() .Border(1) - .Background(Colors.Red.Lighten2) + //.Background(Colors.Red.Lighten2) .Table(table => { table.ColumnsDefinition(columns => diff --git a/QuestPDF/Drawing/SpacePlan.cs b/QuestPDF/Drawing/SpacePlan.cs index abaab78..bca74da 100644 --- a/QuestPDF/Drawing/SpacePlan.cs +++ b/QuestPDF/Drawing/SpacePlan.cs @@ -31,7 +31,7 @@ namespace QuestPDF.Drawing if (Type == SpacePlanType.Wrap) return Type.ToString(); - return $"{Type} (Width: {Width:N2}, Height: {Height:N2})"; + return $"{Type} (Width: {Width:N3}, Height: {Height:N3})"; } public static implicit operator Size(SpacePlan spacePlan) diff --git a/QuestPDF/Elements/Table/Table.cs b/QuestPDF/Elements/Table/Table.cs index 029aed8..003e38d 100644 --- a/QuestPDF/Elements/Table/Table.cs +++ b/QuestPDF/Elements/Table/Table.cs @@ -149,7 +149,7 @@ namespace QuestPDF.Elements.Table } } - private IEnumerable PlanLayout(Size availableSpace) + private ICollection PlanLayout(Size availableSpace) { var cellOffsets = new float[Columns.Count + 1]; cellOffsets[0] = 0; @@ -165,83 +165,86 @@ namespace QuestPDF.Elements.Table var maxRenderingRow = RowsCount; var currentRow = CurrentRow; + + var commands = new List(); - foreach (var child in childrenToTry) + foreach (var cell in childrenToTry) { - if (child.Row > currentRow) + if (cell.Row > currentRow) { rowBottomOffsets[currentRow] = Math.Max(rowBottomOffsets[currentRow], rowBottomOffsets[currentRow - 1]); if (rowBottomOffsets[currentRow - 1] > availableSpace.Height + Size.Epsilon) break; - currentRow = child.Row; + currentRow = cell.Row; } - if (child.Row > maxRenderingRow) + if (cell.Row > maxRenderingRow) break; - if (child.IsRendered) + if (cell.IsRendered) continue; - var topOffset = rowBottomOffsets[child.Row - 1]; + var topOffset = rowBottomOffsets[cell.Row - 1]; var availableHeight = availableSpace.Height - topOffset + Size.Epsilon; - var cellSize = GetCellSize(child, availableHeight); + var cellSize = GetCellSize(cell, availableHeight); if (cellSize.Type == SpacePlanType.PartialRender) { - maxRenderingRow = Math.Min(maxRenderingRow, child.Row + child.RowSpan - 1); + maxRenderingRow = Math.Min(maxRenderingRow, cell.Row + cell.RowSpan - 1); } if (cellSize.Type == SpacePlanType.Wrap) { - maxRenderingRow = Math.Min(maxRenderingRow, child.Row - 1); + maxRenderingRow = Math.Min(maxRenderingRow, cell.Row - 1); continue; } var cellBottomOffset = cellSize.Height + topOffset; - var targetRowId = child.Row + child.RowSpan - 1; // -1 because rowSpan starts at 1 + var targetRowId = cell.Row + cell.RowSpan - 1; // -1 because rowSpan starts at 1 rowBottomOffsets[targetRowId] = Math.Max(rowBottomOffsets[targetRowId], cellBottomOffset); - } - - Console.WriteLine($"{CurrentRow} / {maxRenderingRow}"); - - var rowHeights = new DynamicDictionary(); - - Enumerable - .Range(CurrentRow, rowBottomOffsets.Items.Count) - .ToList() - .ForEach(x => rowHeights[x] = rowBottomOffsets[x] - rowBottomOffsets[x-1]); - - // find rows count to render in this pass - var childrenToDraw = Enumerable - .Range(CurrentRow, maxRenderingRow - CurrentRow + 1) - .SelectMany(x => OrderedChildren[x]); - - foreach (var cell in childrenToDraw) - { - var leftOffset = cellOffsets[cell.Column - 1]; - var topOffset = cell.Row == 1 ? 0 : rowBottomOffsets[cell.Row - 1]; var width = GetCellWidth(cell); - var height = Enumerable.Range(cell.Row, cell.RowSpan).Where(x => x <= maxRenderingRow).Select(x => rowHeights[x]).Sum(); - - var measurement = GetCellSize(cell, height); - - if (measurement.Type == SpacePlanType.Wrap) - continue; - yield return new TableCellRenderingCommand() + var command = new TableCellRenderingCommand() { Cell = cell, - Measurement = measurement, - Size = new Size(width, height), - Offset = new Position(leftOffset, topOffset) + Measurement = cellSize, + Size = new Size(width, cellSize.Height), + Offset = new Position(cellOffsets[cell.Column - 1], topOffset) }; + + commands.Add(command); } + var tableHeight = commands.Max(cell => cell.Offset.Y + cell.Size.Height); + + commands = commands.Where(x => x.Cell.Row <= maxRenderingRow).ToList(); + + foreach (var column in Enumerable.Range(1, Columns.Count)) + { + var lastCellInColumn = commands + .Where(x => x.Cell.Column <= column && column < x.Cell.Column + x.Cell.ColumnSpan) + .OrderByDescending(x => x.Cell.Row + x.Cell.RowSpan) + .FirstOrDefault(); + + if (lastCellInColumn == null) + continue; + + lastCellInColumn.Size = new Size(lastCellInColumn.Size.Width, tableHeight - lastCellInColumn.Offset.Y); + } + + foreach (var command in commands) + { + var height = tableHeight - command.Offset.Y; + command.Size = new Size(command.Size.Width, height); + } + + return commands; + float GetCellWidth(TableCell cell) { return cellOffsets[cell.Column + cell.ColumnSpan - 1] - cellOffsets[cell.Column - 1];