Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 72 additions & 4 deletions Source/FossPDF/Elements/Table/Table.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using FossPDF.Drawing;
using FossPDF.Fluent;
using FossPDF.Infrastructure;

namespace FossPDF.Elements.Table
Expand All @@ -15,6 +12,10 @@ internal class Table : Element, IStateResettable, IContentDirectionAware

public List<TableColumnDefinition> Columns { get; set; } = new();
public List<TableCell> Cells { get; set; } = new();
public List<TableCell> AllCells { get; set; } = new();
public Dictionary<int, float> ColumnsWidth { get; set; } = new();
public Action<Dictionary<int, float>> AfterUpdateColumnsWidth { get; set; }

public bool ExtendLastCellsToTableBottom { get; set; }

private bool CacheInitialized { get; set; }
Expand Down Expand Up @@ -149,6 +150,15 @@ private int FindLastRenderedRow(ICollection<TableCellRenderingCommand> commands)

private void UpdateColumnsWidth(float availableWidth)
{
if (ColumnsWidth.Any())
{
foreach (var column in Columns)
{
column.Width = ColumnsWidth[Columns.IndexOf(column)];
}
return;
}

var constantWidth = Columns.Sum(x => x.ConstantSize);
var relativeWidth = Columns.Sum(x => x.RelativeSize);

Expand All @@ -158,6 +168,64 @@ private void UpdateColumnsWidth(float availableWidth)
{
column.Width = column.ConstantSize + column.RelativeSize * widthPerRelativeUnit;
}

var cells = AllCells.Where(c => c is { ColumnSpan: 1, RowSpan: 1 });

foreach (var column in Columns.Where(c => c.AllowShrink))
{
var index = Columns.IndexOf(column);
var cellsInColumn = cells.Where(c => c.Column == index + 1);
if (cellsInColumn.Any())
{
ColumnsWidth.Add(index, cellsInColumn.Max(c => c.Measure(Size.Max).Width));
column.Width = Math.Min(column.Width, ColumnsWidth[index]);
}
}

var remainingWidth = availableWidth - Columns.Sum(c => c.Width);
while (remainingWidth > 0)
{
var columnsThatGrow = Columns.Where(c => c.AllowGrow).ToList();
var growStep = remainingWidth / columnsThatGrow.Count;
var anyColumnHasGrown = false;
foreach (var column in columnsThatGrow)
{
var index = Columns.IndexOf(column);
var cellsInColumn = cells.Where(c => c.Column == index + 1);
if (!ColumnsWidth.ContainsKey(index))
{
ColumnsWidth.Add(index, cellsInColumn.Max(c => c.Measure(Size.Max).Width));
}
var newWidth = Math.Min(column.Width + growStep, ColumnsWidth[index]);
if (newWidth > column.Width)
{
anyColumnHasGrown = true;
}
column.Width = newWidth;
remainingWidth = availableWidth - Columns.Sum(c => c.Width);
if (remainingWidth <= 0)
{
break;
}
}
if (!anyColumnHasGrown)
{
break;
}
}

if (remainingWidth > 0)
{
Columns.Last().Width += remainingWidth;
}

foreach (var column in Columns)
{
// Add missing columns, that don't auto size.
ColumnsWidth[Columns.IndexOf(column)] = column.Width;
}

AfterUpdateColumnsWidth?.Invoke(ColumnsWidth);
}

private ICollection<TableCellRenderingCommand> PlanLayout(Size availableSpace)
Expand Down Expand Up @@ -309,4 +377,4 @@ float GetCellWidth(TableCell cell)
}
}
}
}
}
9 changes: 7 additions & 2 deletions Source/FossPDF/Elements/Table/TableColumnDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ internal class TableColumnDefinition

internal float Width { get; set; }

public TableColumnDefinition(float constantSize, float relativeSize)
public bool AllowShrink { get; set; }
public bool AllowGrow { get; set; }

public TableColumnDefinition(float constantSize, float relativeSize, bool allowShrink, bool allowGrow)
{
ConstantSize = constantSize;
RelativeSize = relativeSize;
AllowShrink = allowShrink;
AllowGrow = allowGrow;
}
}
}
}
39 changes: 27 additions & 12 deletions Source/FossPDF/Fluent/TableExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using FossPDF.Drawing.Exceptions;
using FossPDF.Elements;
Expand All @@ -14,19 +12,19 @@ public class TableColumnsDefinitionDescriptor
{
internal List<TableColumnDefinition> Columns { get; } = new();

public void ConstantColumn(float width, Unit unit = Unit.Point)
public void ConstantColumn(float width, Unit unit = Unit.Point, bool allowShrink = false, bool allowGrow = false)
{
ComplexColumn(constantWidth: width.ToPoints(unit));
ComplexColumn(allowShrink, allowGrow, constantWidth: width.ToPoints(unit));
}

public void RelativeColumn(float width = 1)
public void RelativeColumn(float width = 1, bool allowShrink = false, bool allowGrow = false)
{
ComplexColumn(relativeWidth: width);
ComplexColumn(allowShrink, allowGrow, relativeWidth: width);
}
private void ComplexColumn(float constantWidth = 0, float relativeWidth = 0)

private void ComplexColumn(bool allowShrink, bool allowGrow, float constantWidth = 0, float relativeWidth = 0)
{
var columnDefinition = new TableColumnDefinition(constantWidth, relativeWidth);
var columnDefinition = new TableColumnDefinition(constantWidth, relativeWidth, allowShrink, allowGrow);
Columns.Add(columnDefinition);
}
}
Expand All @@ -50,8 +48,6 @@ public ITableCellContainer Cell()

public class TableDescriptor
{
internal List<TableColumnDefinition> Columns { get; private set; }

private Table HeaderTable { get; } = new();
private Table ContentTable { get; } = new();
private Table FooterTable { get; } = new();
Expand Down Expand Up @@ -94,6 +90,25 @@ internal IElement CreateElement()
{
var container = new Container();

List<TableCell> allTableCells = new();
var tables = new List<Table>() { HeaderTable, ContentTable, FooterTable };
foreach (var table in tables)
{
allTableCells.AddRange(table.Cells);
table.AfterUpdateColumnsWidth += (columnsWidth) =>
{
foreach (var table in tables)
{
table.ColumnsWidth = columnsWidth;
}
};
}

foreach (var table in tables)
{
table.AllCells = allTableCells;
}

ConfigureTable(HeaderTable);
ConfigureTable(ContentTable);
ConfigureTable(FooterTable);
Expand Down Expand Up @@ -159,4 +174,4 @@ public static ITableCellContainer RowSpan(this ITableCellContainer tableCellCont
return tableCellContainer.TableCell(x => x.RowSpan = (int)value);
}
}
}
}