Browse Source

Table: added support for headers and footers

Marcin Ziąbek 4 years ago
parent
commit
630d3389d3

+ 34 - 46
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); 
                             }
                         });
                 });

+ 3 - 3
QuestPDF/Elements/Table/Table.cs

@@ -11,8 +11,8 @@ namespace QuestPDF.Elements.Table
 {
     internal class Table : Element, IStateResettable
     {
-        public List<TableColumnDefinition> Columns { get; } = new List<TableColumnDefinition>();
-        public List<TableCell> Cells { get; } = new List<TableCell>();
+        public List<TableColumnDefinition> Columns { get; set; } = new List<TableColumnDefinition>();
+        public List<TableCell> Cells { get; set; } = new List<TableCell>();
         public bool ExtendLastCellsToTableBottom { get; set; }
         
         // cache for efficient cell finding
@@ -274,4 +274,4 @@ namespace QuestPDF.Elements.Table
             }
         }
     }
-}
+}

+ 74 - 22
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<TableColumnDefinition> 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<TableCell> Cells { get; }
 
-        internal TableDescriptor(Table table)
+        internal TableCellDescriptor(ICollection<TableCell> cells)
         {
-            Table = table;
+            Cells = cells;
         }
         
+        public ITableCellContainer Cell()
+        {
+            var cell = new TableCell();
+            Cells.Add(cell);
+            return 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();
+
         public void ColumnsDefinition(Action<TableColumnsDefinitionDescriptor> handler)
         {
-            var descriptor = new TableColumnsDefinitionDescriptor(Table);
+            var descriptor = new TableColumnsDefinitionDescriptor();
             handler(descriptor);
+
+            HeaderTable.Columns = descriptor.Columns;
+            ContentTable.Columns = descriptor.Columns;
+            FooterTable.Columns = descriptor.Columns;
         }
         
         public void ExtendLastCellsToTableBottom()
         {
-            Table.ExtendLastCellsToTableBottom = true;
+            ContentTable.ExtendLastCellsToTableBottom = true;
+        }
+        
+        public void Header(Action<TableCellDescriptor> handler)
+        {
+            var descriptor = new TableCellDescriptor(HeaderTable.Cells);
+            handler(descriptor);
+        }
+        
+        public void Footer(Action<TableCellDescriptor> handler)
+        {
+            var descriptor = new TableCellDescriptor(FooterTable.Cells);
+            handler(descriptor);
         }
         
         public ITableCellContainer Cell()
         {
             var cell = new TableCell();
-            Table.Cells.Add(cell);
+            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<TableDescriptor> 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());
         }
     }
 

+ 1 - 1
QuestPDF/QuestPDF.csproj

@@ -4,7 +4,7 @@
         <Authors>MarcinZiabek</Authors>
         <Company>CodeFlint</Company>
         <PackageId>QuestPDF</PackageId>
-        <Version>2022.1.0-beta3</Version>
+        <Version>2022.1.0-beta4</Version>
         <PackageDescription>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.</PackageDescription>
         <PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/Resources/ReleaseNotes.txt"))</PackageReleaseNotes>
         <LangVersion>9</LangVersion>