Table: layouting improvements for paging
This commit is contained in:
committed by
Marcin Ziąbek
parent
96732b5856
commit
ed73c5b82d
@@ -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 =>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace QuestPDF.Elements.Table
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<TableCellRenderingCommand> PlanLayout(Size availableSpace)
|
||||
private ICollection<TableCellRenderingCommand> 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<TableCellRenderingCommand>();
|
||||
|
||||
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<int, float>();
|
||||
|
||||
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];
|
||||
|
||||
Reference in New Issue
Block a user