From 51508bbe0b43d7d1783cda5dfb20d2a057a45298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zi=C4=85bek?= Date: Thu, 6 Jan 2022 21:10:54 +0100 Subject: [PATCH] Table: added support for headers and footers --- QuestPDF.Examples/TableExamples.cs | 80 +++++++++----------- QuestPDF/Elements/Table/Table.cs | 4 +- QuestPDF/Fluent/TableExtensions.cs | 114 +++++++++++++++++++++-------- QuestPDF/QuestPDF.csproj | 2 +- 4 files changed, 120 insertions(+), 80 deletions(-) diff --git a/QuestPDF.Examples/TableExamples.cs b/QuestPDF.Examples/TableExamples.cs index c9eeee1..46c8d63 100644 --- a/QuestPDF.Examples/TableExamples.cs +++ b/QuestPDF.Examples/TableExamples.cs @@ -309,7 +309,7 @@ namespace QuestPDF.Examples .Padding(10) .MinimalBox() .Border(1) - .Decoration(decoration => + .Table(table => { IContainer DefaultCellStyle(IContainer container, string backgroundColor) { @@ -323,51 +323,7 @@ namespace QuestPDF.Examples .AlignMiddle(); } - decoration - .Header() - .DefaultTextStyle(TextStyle.Default.SemiBold()) - .Table(table => - { - table.ColumnsDefinition(DefineTableColumns); - - table.Cell().RowSpan(2).Element(CellStyle).ExtendHorizontal().AlignLeft().Text("Document type"); - - table.Cell().ColumnSpan(2).Element(CellStyle).Text("Inches"); - table.Cell().ColumnSpan(2).Element(CellStyle).Text("Points"); - - table.Cell().Element(CellStyle).Text("Width"); - table.Cell().Element(CellStyle).Text("Height"); - - table.Cell().Element(CellStyle).Text("Width"); - table.Cell().Element(CellStyle).Text("Height"); - - // you can extend already existing styles by creating additional methods - IContainer CellStyle(IContainer container) => DefaultCellStyle(container, Colors.Grey.Lighten3); - }); - - decoration - .Content() - .Table(table => - { - table.ColumnsDefinition(DefineTableColumns); - - foreach (var page in pageSizes) - { - table.Cell().Element(CellStyle).ExtendHorizontal().AlignLeft().Text(page.name); - - // inches - table.Cell().Element(CellStyle).Text(page.width); - table.Cell().Element(CellStyle).Text(page.height); - - // points - table.Cell().Element(CellStyle).Text(page.width * inchesToPoints); - table.Cell().Element(CellStyle).Text(page.height * inchesToPoints); - - IContainer CellStyle(IContainer container) => DefaultCellStyle(container, Colors.White); - } - }); - - void DefineTableColumns(TableColumnsDefinitionDescriptor columns) + table.ColumnsDefinition(columns => { columns.RelativeColumn(); @@ -376,6 +332,38 @@ namespace QuestPDF.Examples columns.ConstantColumn(75); columns.ConstantColumn(75); + }); + + table.Header(header => + { + header.Cell().RowSpan(2).Element(CellStyle).ExtendHorizontal().AlignLeft().Text("Document type"); + + header.Cell().ColumnSpan(2).Element(CellStyle).Text("Inches"); + header.Cell().ColumnSpan(2).Element(CellStyle).Text("Points"); + + header.Cell().Element(CellStyle).Text("Width"); + header.Cell().Element(CellStyle).Text("Height"); + + header.Cell().Element(CellStyle).Text("Width"); + header.Cell().Element(CellStyle).Text("Height"); + + // you can extend already existing styles by creating additional methods + IContainer CellStyle(IContainer container) => DefaultCellStyle(container, Colors.Grey.Lighten3); + }); + + foreach (var page in pageSizes) + { + table.Cell().Element(CellStyle).ExtendHorizontal().AlignLeft().Text(page.name); + + // inches + table.Cell().Element(CellStyle).Text(page.width); + table.Cell().Element(CellStyle).Text(page.height); + + // points + table.Cell().Element(CellStyle).Text(page.width * inchesToPoints); + table.Cell().Element(CellStyle).Text(page.height * inchesToPoints); + + IContainer CellStyle(IContainer container) => DefaultCellStyle(container, Colors.White); } }); }); diff --git a/QuestPDF/Elements/Table/Table.cs b/QuestPDF/Elements/Table/Table.cs index 89df77d..207c2f1 100644 --- a/QuestPDF/Elements/Table/Table.cs +++ b/QuestPDF/Elements/Table/Table.cs @@ -11,8 +11,8 @@ namespace QuestPDF.Elements.Table { internal class Table : Element, IStateResettable { - public List Columns { get; } = new List(); - public List Cells { get; } = new List(); + public List Columns { get; set; } = new List(); + public List Cells { get; set; } = new List(); public bool ExtendLastCellsToTableBottom { get; set; } // cache for efficient cell finding diff --git a/QuestPDF/Fluent/TableExtensions.cs b/QuestPDF/Fluent/TableExtensions.cs index 09d50b3..8e66257 100644 --- a/QuestPDF/Fluent/TableExtensions.cs +++ b/QuestPDF/Fluent/TableExtensions.cs @@ -1,5 +1,8 @@ using System; +using System.Collections; +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using QuestPDF.Drawing.Exceptions; using QuestPDF.Elements; using QuestPDF.Elements.Table; @@ -9,12 +12,7 @@ namespace QuestPDF.Fluent { public class TableColumnsDefinitionDescriptor { - private Table Table { get; } - - internal TableColumnsDefinitionDescriptor(Table table) - { - Table = table; - } + internal List Columns { get; } = new(); public void ConstantColumn(float width) { @@ -29,51 +27,105 @@ namespace QuestPDF.Fluent public void ComplexColumn(float constantWidth = 0, float relativeWidth = 0) { var columnDefinition = new TableColumnDefinition(constantWidth, relativeWidth); - Table.Columns.Add(columnDefinition); + Columns.Add(columnDefinition); } } - public class TableDescriptor + public class TableCellDescriptor { - private Table Table { get; } + private ICollection Cells { get; } - internal TableDescriptor(Table table) + internal TableCellDescriptor(ICollection cells) { - Table = table; - } - - public void ColumnsDefinition(Action handler) - { - var descriptor = new TableColumnsDefinitionDescriptor(Table); - handler(descriptor); - } - - public void ExtendLastCellsToTableBottom() - { - Table.ExtendLastCellsToTableBottom = true; + Cells = cells; } public ITableCellContainer Cell() { var cell = new TableCell(); - Table.Cells.Add(cell); + Cells.Add(cell); return cell; } } + public class TableDescriptor + { + internal List Columns { get; private set; } + + private Table HeaderTable { get; } = new(); + private Table ContentTable { get; } = new(); + private Table FooterTable { get; } = new(); + + public void ColumnsDefinition(Action handler) + { + var descriptor = new TableColumnsDefinitionDescriptor(); + handler(descriptor); + + HeaderTable.Columns = descriptor.Columns; + ContentTable.Columns = descriptor.Columns; + FooterTable.Columns = descriptor.Columns; + } + + public void ExtendLastCellsToTableBottom() + { + ContentTable.ExtendLastCellsToTableBottom = true; + } + + public void Header(Action handler) + { + var descriptor = new TableCellDescriptor(HeaderTable.Cells); + handler(descriptor); + } + + public void Footer(Action handler) + { + var descriptor = new TableCellDescriptor(FooterTable.Cells); + handler(descriptor); + } + + public ITableCellContainer Cell() + { + var cell = new TableCell(); + ContentTable.Cells.Add(cell); + return cell; + } + + internal IElement CreateElement() + { + var container = new Container(); + + ConfigureTable(HeaderTable); + ConfigureTable(ContentTable); + ConfigureTable(FooterTable); + + container + .Decoration(decoration => + { + decoration.Header().Element(HeaderTable); + decoration.Content().Element(ContentTable); + decoration.Footer().Element(FooterTable); + }); + + return container; + } + + private static void ConfigureTable(Table table) + { + if (!table.Columns.Any()) + throw new DocumentComposeException($"Table should have at least one column. Please call the '{nameof(ColumnsDefinition)}' method to define columns."); + + table.PlanCellPositions(); + table.ValidateCellPositions(); + } + } + public static class TableExtensions { public static void Table(this IContainer element, Action handler) { - var table = new Table(); - - var descriptor = new TableDescriptor(table); + var descriptor = new TableDescriptor(); handler(descriptor); - - table.PlanCellPositions(); - table.ValidateCellPositions(); - - element.Element(table); + element.Element(descriptor.CreateElement()); } } diff --git a/QuestPDF/QuestPDF.csproj b/QuestPDF/QuestPDF.csproj index 57cc018..107d1e6 100644 --- a/QuestPDF/QuestPDF.csproj +++ b/QuestPDF/QuestPDF.csproj @@ -4,7 +4,7 @@ MarcinZiabek CodeFlint QuestPDF - 2022.1.0-beta3 + 2022.1.0-beta4 QuestPDF is an open-source, modern and battle-tested library that can help you with generating PDF documents by offering friendly, discoverable and predictable C# fluent API. $([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/Resources/ReleaseNotes.txt")) 9