Forráskód Böngészése

Dynamic Component: added more examples

MarcinZiabek 3 éve
szülő
commit
e51082400c

+ 98 - 0
QuestPDF.Examples/DynamicFibonacci.cs

@@ -0,0 +1,98 @@
+using System.Collections.Generic;
+using System.Linq;
+using NUnit.Framework;
+using QuestPDF.Elements;
+using QuestPDF.Examples.Engine;
+using QuestPDF.Fluent;
+using QuestPDF.Helpers;
+using QuestPDF.Infrastructure;
+
+namespace QuestPDF.Examples
+{
+    public struct FibonacciHeaderState
+    {
+        public int Previous { get; set; }
+        public int Current { get; set; }
+    }
+    
+    public class FibonacciHeader : IDynamicComponent<FibonacciHeaderState>
+    {
+        public FibonacciHeaderState State { get; set; }
+        
+        public static readonly string[] ColorsTable =
+        {
+            Colors.Red.Lighten2,
+            Colors.Orange.Lighten2,
+            Colors.Green.Lighten2,
+        };
+
+        public FibonacciHeader(int previous, int current)
+        {
+            State = new FibonacciHeaderState
+            {
+                Previous = previous,
+                Current = current
+            };
+        }
+
+        public DynamicComponentComposeResult Compose(DynamicContext context)
+        {
+            var content = context.CreateElement(container =>
+            {
+                var colorIndex = State.Current % ColorsTable.Length;
+                var color = ColorsTable[colorIndex];
+
+                var ratio = (float)State.Current / State.Previous;
+                
+                container
+                    .Background(color)
+                    .Height(50)
+                    .AlignMiddle()
+                    .AlignCenter()
+                    .Text($"{State.Current} / {State.Previous} = {ratio:N5}");
+            });
+
+            State = new FibonacciHeaderState
+            {
+                Previous = State.Current,
+                Current = State.Previous + State.Current
+            };
+            
+            return new DynamicComponentComposeResult
+            {
+                Content = content,
+                HasMoreContent = false
+            };
+        }
+    }
+    
+    public static class DynamicFibonacci
+    {
+        [Test]
+        public static void Dynamic()
+        {
+            RenderingTest
+                .Create()
+                .ShowResults()
+                .MaxPages(100)
+                .ProducePdf()
+                .RenderDocument(container =>
+                {
+                    container.Page(page =>
+                    {
+                        page.Size(PageSizes.A6);
+                        page.Margin(1, Unit.Centimetre);
+                        page.DefaultTextStyle(x => x.FontSize(18));
+
+                        page.Header().Dynamic(new FibonacciHeader(17, 19));
+                        
+                        page.Content().Column(column =>
+                        {
+                            foreach (var i in Enumerable.Range(0, 100))
+                                column.Item().PaddingTop(25).Background(Colors.Grey.Lighten2).Height(50);
+                        });
+                    });
+                });
+        }
+    }
+}

+ 5 - 5
QuestPDF.Examples/DynamicExamples.cs → QuestPDF.Examples/DynamicOptimizedExample.cs

@@ -21,12 +21,12 @@ namespace QuestPDF.Examples
         public int ShownItemsCount { get; set; }
     }
     
-    public class OrdersTable : IDynamicComponent<OrdersTableState>
+    public class OptimizedOrdersTable : IDynamicComponent<OrdersTableState>
     {
         private ICollection<OrderItem> Items { get; }
         public OrdersTableState State { get; set; }
 
-        public OrdersTable(ICollection<OrderItem> items)
+        public OptimizedOrdersTable(ICollection<OrderItem> items)
         {
             Items = items;
 
@@ -69,7 +69,7 @@ namespace QuestPDF.Examples
             return new DynamicComponentComposeResult
             {
                 Content = content,
-                HasMoreContent = State.ShownItemsCount + rows.Count < Items.Count
+                HasMoreContent = State.ShownItemsCount < Items.Count
             };
         }
 
@@ -145,7 +145,7 @@ namespace QuestPDF.Examples
         }
     }
     
-    public static class DynamicExamples
+    public static class DynamicOptimizedExamples
     {
         [Test]
         public static void Dynamic()
@@ -177,7 +177,7 @@ namespace QuestPDF.Examples
                             
                             decoration
                                 .Content()
-                                .Dynamic(new OrdersTable(items));
+                                .Dynamic(new OptimizedOrdersTable(items));
                         });
                 });
         }

+ 66 - 0
QuestPDF.Examples/DynamicProgressHeader.cs

@@ -0,0 +1,66 @@
+using System.Collections.Generic;
+using System.Linq;
+using NUnit.Framework;
+using QuestPDF.Elements;
+using QuestPDF.Examples.Engine;
+using QuestPDF.Fluent;
+using QuestPDF.Helpers;
+using QuestPDF.Infrastructure;
+
+namespace QuestPDF.Examples
+{
+    public class ProgressHeader : IDynamicComponent<int>
+    {
+        public int State { get; set; }
+        
+        public DynamicComponentComposeResult Compose(DynamicContext context)
+        {
+            var content = context.CreateElement(container =>
+            {
+                var width = context.AvailableSize.Width * context.PageNumber / context.TotalPages;
+                
+                container
+                    .Background(Colors.Blue.Lighten2)
+                    .Height(25)
+                    .Width(width)
+                    .Background(Colors.Blue.Darken1);
+            });
+
+            return new DynamicComponentComposeResult
+            {
+                Content = content,
+                HasMoreContent = false
+            };
+        }
+    }
+    
+    public static class DynamicProgressHeader
+    {
+        [Test]
+        public static void Dynamic()
+        {
+            RenderingTest
+                .Create()
+                .ShowResults()
+                .MaxPages(100)
+                .ProducePdf()
+                .RenderDocument(container =>
+                {
+                    container.Page(page =>
+                    {
+                        page.Size(PageSizes.A6);
+                        page.Margin(1, Unit.Centimetre);
+                        page.DefaultTextStyle(x => x.FontSize(20));
+
+                        page.Header().Dynamic(new ProgressHeader());
+                        
+                        page.Content().Column(column =>
+                        {
+                            foreach (var i in Enumerable.Range(0, 100))
+                                column.Item().PaddingTop(25).Background(Colors.Grey.Lighten2).Height(50);
+                        });
+                    });
+                });
+        }
+    }
+}

+ 154 - 0
QuestPDF.Examples/DynamicSimpleTableExample.cs

@@ -0,0 +1,154 @@
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using NUnit.Framework;
+using QuestPDF.Elements;
+using QuestPDF.Examples.Engine;
+using QuestPDF.Fluent;
+using QuestPDF.Helpers;
+using QuestPDF.Infrastructure;
+
+namespace QuestPDF.Examples
+{
+    public class OrdersTable : IDynamicComponent<OrdersTableState>
+    {
+        private IList<OrderItem> Items { get; }
+        public OrdersTableState State { get; set; }
+
+        public OrdersTable(IList<OrderItem> items)
+        {
+            Items = items;
+
+            State = new OrdersTableState
+            {
+                ShownItemsCount = 0
+            };
+        }
+        
+        public DynamicComponentComposeResult Compose(DynamicContext context)
+        {
+            var possibleItems = Enumerable
+                .Range(1, Items.Count - State.ShownItemsCount)
+                .Select(itemsToDisplay => ComposeContent(context, itemsToDisplay))
+                .TakeWhile(x => x.Size.Height <= context.AvailableSize.Height)
+                .ToList();
+
+            State = new OrdersTableState
+            {
+                ShownItemsCount = State.ShownItemsCount + possibleItems.Count
+            };
+
+            return new DynamicComponentComposeResult
+            {
+                Content = possibleItems.Last(),
+                HasMoreContent = State.ShownItemsCount < Items.Count
+            };
+        }
+
+        private IDynamicElement ComposeContent(DynamicContext context, int itemsToDisplay)
+        {
+            var total = Items.Skip(State.ShownItemsCount).Take(itemsToDisplay).Sum(x => x.Count * x.Price);
+
+            return context.CreateElement(container =>
+            {
+                container
+                    .MinimalBox()
+                    .Width(context.AvailableSize.Width)
+                    .Table(table =>
+                    {
+                        table.ColumnsDefinition(columns =>
+                        {
+                            columns.ConstantColumn(30);
+                            columns.RelativeColumn();
+                            columns.ConstantColumn(50);
+                            columns.ConstantColumn(50);
+                            columns.ConstantColumn(50);
+                        });
+                        
+                        table.Header(header =>
+                        {
+                            header.Cell().Element(Style).Text("#");
+                            header.Cell().Element(Style).Text("Item name");
+                            header.Cell().Element(Style).AlignRight().Text("Count");
+                            header.Cell().Element(Style).AlignRight().Text("Price");
+                            header.Cell().Element(Style).AlignRight().Text("Total");
+
+                            IContainer Style(IContainer container)
+                            {
+                                return container
+                                    .DefaultTextStyle(x => x.SemiBold())
+                                    .BorderBottom(1)
+                                    .BorderColor(Colors.Grey.Darken2)
+                                    .Padding(5);
+                            }
+                        });
+                        
+                        table.Footer(footer =>
+                        {
+                            footer
+                                .Cell().ColumnSpan(5)
+                                .AlignRight()
+                                .Text($"Subtotal: {total}$", TextStyle.Default.Size(14).SemiBold());
+                        });
+                        
+                        foreach (var index in Enumerable.Range(State.ShownItemsCount, itemsToDisplay))
+                        {
+                            var item = Items[index];
+                                
+                            table.Cell().Element(Style).Text(index + 1);
+                            table.Cell().Element(Style).Text(item.ItemName);
+                            table.Cell().Element(Style).AlignRight().Text(item.Count);
+                            table.Cell().Element(Style).AlignRight().Text($"{item.Price}$");
+                            table.Cell().Element(Style).AlignRight().Text($"{item.Count*item.Price}$");
+
+                            IContainer Style(IContainer container)
+                            {
+                                return container
+                                    .BorderBottom(1)
+                                    .BorderColor(Colors.Grey.Lighten2)
+                                    .Padding(5);
+                            }
+                        }
+                    });
+            });
+        }
+    }
+    
+    public static class DynamicSimpleTableExample
+    {
+        [Test]
+        public static void Dynamic()
+        {
+            RenderingTest
+                .Create()
+                .PageSize(PageSizes.A5)
+                .ShowResults()
+                .Render(container =>
+                {
+                    var items = Enumerable.Range(0, 25).Select(x => new OrderItem()).ToList();
+                    
+                    container
+                        .Background(Colors.White)
+                        .Padding(25)
+                        .Decoration(decoration =>
+                        {
+                            decoration
+                                .Header()
+                                .PaddingBottom(5)
+                                .Text(text =>
+                                {
+                                    text.DefaultTextStyle(TextStyle.Default.SemiBold().FontColor(Colors.Blue.Darken2).FontSize(16));
+                                    text.Span("Page ");
+                                    text.CurrentPageNumber();
+                                    text.Span(" / ");
+                                    text.TotalPages();
+                                });
+                            
+                            decoration
+                                .Content()
+                                .Dynamic(new OrdersTable(items));
+                        });
+                });
+        }
+    }
+}

+ 2 - 0
QuestPDF/Elements/Dynamic.cs

@@ -52,6 +52,7 @@ namespace QuestPDF.Elements
             var context = new DynamicContext
             {
                 PageNumber = PageContext.CurrentPage,
+                TotalPages = PageContext.GetLocation(Infrastructure.PageContext.DocumentLocation).PageEnd,
                 PageContext = PageContext,
                 Canvas = Canvas,
                 TextStyle = TextStyle,
@@ -75,6 +76,7 @@ namespace QuestPDF.Elements
         internal TextStyle TextStyle { get; set; }
     
         public int PageNumber { get; internal set; }
+        public int TotalPages { get; internal set; }
         public Size AvailableSize { get; internal set; }
 
         public IDynamicElement CreateElement(Action<IContainer> content)

+ 3 - 3
QuestPDF/Resources/ReleaseNotes.txt

@@ -1,4 +1,4 @@
-- Implemented the DynamicComponent element (useful for most advanced cases, e.g. per-page totals),
-- Extend text rendering capabilities by adding subscript and superscript effects,
+- Implemented the DynamicComponent element (useful when you want to generate dynamic and conditional content that is page aware, e.g. per-page totals),
+- Extended text rendering capabilities by adding subscript and superscript effects,
 - Improved table rendering performance,
-- Previewer tool stability fixes.
+- Previewer tool stability fixes.