Browse Source

Dynamic: simplified container composition process

MarcinZiabek 3 years ago
parent
commit
a2629575e8

+ 18 - 12
QuestPDF.Examples/DynamicExamples.cs

@@ -36,7 +36,7 @@ namespace QuestPDF.Examples
             };
         }
         
-        public void Compose(DynamicContext context, IDynamicContainer container)
+        public DynamicComponentComposeResult Compose(DynamicContext context)
         {
             var header = ComposeHeader(context);
             var sampleFooter = ComposeFooter(context, Enumerable.Empty<OrderItem>());
@@ -45,26 +45,32 @@ namespace QuestPDF.Examples
             var rows = GetItemsForPage(context, decorationHeight).ToList();
             var footer = ComposeFooter(context, rows.Select(x => x.Item));
 
-            if (State.ShownItemsCount + rows.Count < Items.Count)
-                container.HasMoreContent();
-            
-            container.MinimalBox().Decoration(decoration =>
+            var content = context.CreateElement(container =>
             {
-                decoration.Header().Element(header);
-                
-                decoration.Content().Box().Stack(stack =>
+                container.MinimalBox().Decoration(decoration =>
                 {
-                    foreach (var row in rows)
-                        stack.Item().Element(row.Element);
-                });
+                    decoration.Header().Element(header);
+
+                    decoration.Content().Box().Stack(stack =>
+                    {
+                        foreach (var row in rows)
+                            stack.Item().Element(row.Element);
+                    });
 
-                decoration.Footer().Element(footer);
+                    decoration.Footer().Element(footer);
+                });
             });
 
             State = new OrdersTableState
             {
                 ShownItemsCount = State.ShownItemsCount + rows.Count
             };
+
+            return new DynamicComponentComposeResult
+            {
+                Content = content,
+                HasMoreContent = State.ShownItemsCount + rows.Count < Items.Count
+            };
         }
 
         private IDynamicElement ComposeHeader(DynamicContext context)

+ 8 - 29
QuestPDF/Elements/Dynamic.cs

@@ -27,23 +27,25 @@ namespace QuestPDF.Elements
         
         internal override SpacePlan Measure(Size availableSpace)
         {
-            var content = GetContent(availableSpace, acceptNewState: false);
+            var result = GetContent(availableSpace, acceptNewState: false);
+            var content = result.Content as Element ?? Empty.Instance;
             var measurement = content.Measure(availableSpace);
 
             if (measurement.Type != SpacePlanType.FullRender)
                 throw new DocumentLayoutException("Dynamic component generated content that does not fit on a single page.");
             
-            return content.HasMoreContent 
+            return result.HasMoreContent 
                 ? SpacePlan.PartialRender(measurement) 
                 : SpacePlan.FullRender(measurement);
         }
 
         internal override void Draw(Size availableSpace)
         {
-            GetContent(availableSpace, acceptNewState: true).Draw(availableSpace);
+            var content = GetContent(availableSpace, acceptNewState: true).Content as Element; 
+            content?.Draw(availableSpace);
         }
 
-        private DynamicContainer GetContent(Size availableSize, bool acceptNewState)
+        private DynamicComponentComposeResult GetContent(Size availableSize, bool acceptNewState)
         {
             var componentState = Child.GetState();
             
@@ -57,16 +59,12 @@ namespace QuestPDF.Elements
                 AvailableSize = availableSize
             };
             
-            var container = new DynamicContainer();
-            Child.Compose(context, container);
+            var result = Child.Compose(context);
 
             if (!acceptNewState)
                 Child.SetState(componentState);
 
-            container.VisitChildren(x => x?.Initialize(PageContext, Canvas));
-            container.VisitChildren(x => (x as IStateResettable)?.ResetState());
-            
-            return container;
+            return result;
         }
     }
 
@@ -94,25 +92,6 @@ namespace QuestPDF.Elements
         }
     }
 
-    public interface IDynamicContainer : IContainer
-    {
-        
-    }
-
-    internal class DynamicContainer : Container, IDynamicContainer
-    {
-        internal bool HasMoreContent { get; set; }
-    }
-
-    public static class DynamicContainerExtensions
-    {
-        public static IDynamicContainer HasMoreContent(this IDynamicContainer container)
-        {
-            (container as DynamicContainer).HasMoreContent = true;
-            return container;
-        }
-    }
-    
     public interface IDynamicElement : IElement
     {
         Size Size { get; }

+ 8 - 2
QuestPDF/Infrastructure/IDynamicComponent.cs

@@ -8,7 +8,7 @@ namespace QuestPDF.Infrastructure
     {
         internal Action<object> SetState { get; private set; }
         internal Func<object> GetState { get; private set; }
-        internal Action<DynamicContext, IDynamicContainer> Compose { get; private set; }
+        internal Func<DynamicContext, DynamicComponentComposeResult> Compose { get; private set; }
         
         internal static DynamicComponentProxy CreateFrom<TState>(IDynamicComponent<TState> component) where TState : struct
         {
@@ -20,10 +20,16 @@ namespace QuestPDF.Infrastructure
             };
         }
     }
+
+    public class DynamicComponentComposeResult
+    {
+        public IElement Content { get; set; }
+        public bool HasMoreContent { get; set; }
+    }
     
     public interface IDynamicComponent<TState> where TState : struct
     {
         TState State { get; set; }
-        void Compose(DynamicContext context, IDynamicContainer dynamicContainer);
+        DynamicComponentComposeResult Compose(DynamicContext context);
     }
 }