Browse Source

Fixed #609: the page number functionality for sections do not work
Refactoring: handling of page numbers in sections

MarcinZiabek 2 years ago
parent
commit
b89c876ac4

+ 26 - 32
Source/QuestPDF/Drawing/DocumentGenerator.cs

@@ -105,10 +105,12 @@ namespace QuestPDF.Drawing
         private static void RenderSingleDocument<TCanvas>(TCanvas canvas, IDocument document, DocumentSettings settings)
         private static void RenderSingleDocument<TCanvas>(TCanvas canvas, IDocument document, DocumentSettings settings)
             where TCanvas : ICanvas, IRenderingCanvas
             where TCanvas : ICanvas, IRenderingCanvas
         {
         {
+            const int documentId = 0;
+            
             var debuggingState = new DebuggingState();
             var debuggingState = new DebuggingState();
             var useOriginalImages = canvas is ImageCanvas;
             var useOriginalImages = canvas is ImageCanvas;
 
 
-            var content = ConfigureContent(document, settings, debuggingState, 0, useOriginalImages);
+            var content = ConfigureContent(document, settings, debuggingState, documentId, useOriginalImages);
 
 
             var pageContext = new PageContext();
             var pageContext = new PageContext();
             RenderPass(pageContext, new FreeCanvas(), content, debuggingState);
             RenderPass(pageContext, new FreeCanvas(), content, debuggingState);
@@ -122,31 +124,43 @@ namespace QuestPDF.Drawing
             var debuggingState = new DebuggingState();
             var debuggingState = new DebuggingState();
             var useOriginalImages = canvas is ImageCanvas;
             var useOriginalImages = canvas is ImageCanvas;
             
             
-            var documentContents = Enumerable
+            var documentParts = Enumerable
                 .Range(0, document.Documents.Count)
                 .Range(0, document.Documents.Count)
-                .Select(index => ConfigureContent(document.Documents[index], settings, debuggingState, index, useOriginalImages))
+                .Select(index => new
+                {
+                    DocumentId = index,
+                    Content = ConfigureContent(document.Documents[index], settings, debuggingState, index, useOriginalImages)
+                })
                 .ToList();
                 .ToList();
 
 
             if (document.PageNumberStrategy == MergedDocumentPageNumberStrategy.Continuous)
             if (document.PageNumberStrategy == MergedDocumentPageNumberStrategy.Continuous)
             {
             {
                 var documentPageContext = new PageContext();
                 var documentPageContext = new PageContext();
-                
-                foreach (var content in documentContents)
-                    RenderPass(documentPageContext, new FreeCanvas(), content, debuggingState);
+
+                foreach (var documentPart in documentParts)
+                {
+                    documentPageContext.SetDocumentId(documentPart.DocumentId);
+                    RenderPass(documentPageContext, new FreeCanvas(), documentPart.Content, debuggingState);
+                }
                 
                 
                 documentPageContext.ResetPageNumber();
                 documentPageContext.ResetPageNumber();
-                
-                foreach (var content in documentContents)
-                    RenderPass(documentPageContext, canvas, content, debuggingState);
+
+                foreach (var documentPart in documentParts)
+                {
+                    documentPageContext.SetDocumentId(documentPart.DocumentId);
+                    RenderPass(documentPageContext, canvas, documentPart.Content, debuggingState);   
+                }
             }
             }
             else
             else
             {
             {
-                foreach (var content in documentContents)
+                foreach (var documentPart in documentParts)
                 {
                 {
                     var pageContext = new PageContext();
                     var pageContext = new PageContext();
-                    RenderPass(pageContext, new FreeCanvas(), content, debuggingState);
+                    pageContext.SetDocumentId(documentPart.DocumentId);
+                    
+                    RenderPass(pageContext, new FreeCanvas(), documentPart.Content, debuggingState);
                     pageContext.ResetPageNumber();
                     pageContext.ResetPageNumber();
-                    RenderPass(pageContext, canvas, content, debuggingState);
+                    RenderPass(pageContext, canvas, documentPart.Content, debuggingState);
                 }
                 }
             }
             }
         }
         }
@@ -158,7 +172,6 @@ namespace QuestPDF.Drawing
             
             
             var content = container.Compose();
             var content = container.Compose();
             
             
-            content.ApplyDocumentId(documentIndex);
             content.ApplyInheritedAndGlobalTexStyle(TextStyle.Default);
             content.ApplyInheritedAndGlobalTexStyle(TextStyle.Default);
             content.ApplyContentDirection(settings.ContentDirection);
             content.ApplyContentDirection(settings.ContentDirection);
             content.ApplyDefaultImageConfiguration(settings.ImageRasterDpi, settings.ImageCompressionQuality, useOriginalImages);
             content.ApplyDefaultImageConfiguration(settings.ImageRasterDpi, settings.ImageCompressionQuality, useOriginalImages);
@@ -341,24 +354,5 @@ namespace QuestPDF.Drawing
             foreach (var child in content.GetChildren())
             foreach (var child in content.GetChildren())
                 ApplyInheritedAndGlobalTexStyle(child, documentDefaultTextStyle);
                 ApplyInheritedAndGlobalTexStyle(child, documentDefaultTextStyle);
         }
         }
-        
-        /// <summary>
-        /// This method is important when merging multiple documents together.
-        /// Applying unique document Id to all section names and associated links, prevents from name collisions.
-        /// </summary>
-        internal static void ApplyDocumentId(this Element? content, int documentId = 0)
-        {
-            content.VisitChildren(x =>
-            {
-                if (x is Section section)
-                    section.DocumentId = documentId;
-                
-                else if (x is SectionLink sectionLink)
-                    sectionLink.DocumentId = documentId;
-                
-                else if (x is DynamicHost dynamicHost)
-                    dynamicHost.DocumentId = documentId;
-            });
-        }
     }
     }
 }
 }

+ 2 - 7
Source/QuestPDF/Elements/Dynamic.cs

@@ -14,8 +14,6 @@ namespace QuestPDF.Elements
         internal TextStyle TextStyle { get; set; } = TextStyle.Default;
         internal TextStyle TextStyle { get; set; } = TextStyle.Default;
         public ContentDirection ContentDirection { get; set; }
         public ContentDirection ContentDirection { get; set; }
         
         
-        internal int DocumentId { get; set; }
-        
         internal int? ImageTargetDpi { get; set; }
         internal int? ImageTargetDpi { get; set; }
         internal ImageCompressionQuality? ImageCompressionQuality { get; set; }
         internal ImageCompressionQuality? ImageCompressionQuality { get; set; }
         internal bool UseOriginalImage { get; set; }
         internal bool UseOriginalImage { get; set; }
@@ -60,7 +58,6 @@ namespace QuestPDF.Elements
             {
             {
                 PageContext = PageContext,
                 PageContext = PageContext,
                 Canvas = Canvas,
                 Canvas = Canvas,
-                DocumentId = DocumentId,
                 
                 
                 TextStyle = TextStyle,
                 TextStyle = TextStyle,
                 ContentDirection = ContentDirection,
                 ContentDirection = ContentDirection,
@@ -70,7 +67,7 @@ namespace QuestPDF.Elements
                 UseOriginalImage = UseOriginalImage,
                 UseOriginalImage = UseOriginalImage,
                 
                 
                 PageNumber = PageContext.CurrentPage,
                 PageNumber = PageContext.CurrentPage,
-                TotalPages = PageContext.GetLocation(Infrastructure.PageContext.DocumentLocation).PageEnd,
+                TotalPages = PageContext.DocumentLength,
                 AvailableSize = availableSize
                 AvailableSize = availableSize
             };
             };
             
             
@@ -87,8 +84,7 @@ namespace QuestPDF.Elements
     {
     {
         internal IPageContext PageContext { get; set; }
         internal IPageContext PageContext { get; set; }
         internal ICanvas Canvas { get; set; }
         internal ICanvas Canvas { get; set; }
-        internal int DocumentId { get; set; }
-        
+
         internal TextStyle TextStyle { get; set; }
         internal TextStyle TextStyle { get; set; }
         internal ContentDirection ContentDirection { get; set; }
         internal ContentDirection ContentDirection { get; set; }
 
 
@@ -105,7 +101,6 @@ namespace QuestPDF.Elements
             var container = new DynamicElement();
             var container = new DynamicElement();
             content(container);
             content(container);
             
             
-            container.ApplyDocumentId(DocumentId);
             container.ApplyInheritedAndGlobalTexStyle(TextStyle);
             container.ApplyInheritedAndGlobalTexStyle(TextStyle);
             container.ApplyContentDirection(ContentDirection);
             container.ApplyContentDirection(ContentDirection);
             container.ApplyDefaultImageConfiguration(ImageTargetDpi, ImageCompressionQuality, UseOriginalImage);
             container.ApplyDefaultImageConfiguration(ImageTargetDpi, ImageCompressionQuality, UseOriginalImage);

+ 2 - 9
Source/QuestPDF/Elements/Section.cs

@@ -4,7 +4,6 @@ namespace QuestPDF.Elements
 {
 {
     internal class Section : ContainerElement, IStateResettable
     internal class Section : ContainerElement, IStateResettable
     {
     {
-        public int DocumentId { get; set; }
         public string SectionName { get; set; }
         public string SectionName { get; set; }
         private bool IsRendered { get; set; }
         private bool IsRendered { get; set; }
         
         
@@ -15,21 +14,15 @@ namespace QuestPDF.Elements
         
         
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)
         {
         {
-            var targetName = GetTargetName(DocumentId, SectionName);
-            
             if (!IsRendered)
             if (!IsRendered)
             {
             {
+                var targetName = PageContext.GetDocumentLocationName(SectionName);
                 Canvas.DrawSection(targetName);
                 Canvas.DrawSection(targetName);
                 IsRendered = true;
                 IsRendered = true;
             }
             }
             
             
-            PageContext.SetSectionPage(targetName);
+            PageContext.SetSectionPage(SectionName);
             base.Draw(availableSpace);
             base.Draw(availableSpace);
         }
         }
-        
-        internal static string GetTargetName(int documentId, string locationName)
-        {
-            return $"{documentId} | {locationName}";
-        }
     }
     }
 }
 }

+ 1 - 2
Source/QuestPDF/Elements/SectionLink.cs

@@ -5,7 +5,6 @@ namespace QuestPDF.Elements
 {
 {
     internal class SectionLink : ContainerElement
     internal class SectionLink : ContainerElement
     {
     {
-        public int DocumentId { get; set; }
         public string SectionName { get; set; }
         public string SectionName { get; set; }
         
         
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)
@@ -15,7 +14,7 @@ namespace QuestPDF.Elements
             if (targetSize.Type == SpacePlanType.Wrap)
             if (targetSize.Type == SpacePlanType.Wrap)
                 return;
                 return;
 
 
-            var targetName = Section.GetTargetName(DocumentId, SectionName);
+            var targetName = PageContext.GetDocumentLocationName(SectionName);
             Canvas.DrawSectionLink(targetName, targetSize);
             Canvas.DrawSectionLink(targetName, targetSize);
             base.Draw(availableSpace);
             base.Draw(availableSpace);
         }
         }

+ 1 - 1
Source/QuestPDF/Fluent/TextExtensions.cs

@@ -163,7 +163,7 @@ namespace QuestPDF.Fluent
         
         
         public TextPageNumberDescriptor TotalPages()
         public TextPageNumberDescriptor TotalPages()
         {
         {
-            return PageNumber(x => x.GetLocation(PageContext.DocumentLocation)?.Length);
+            return PageNumber(x => x.DocumentLength);
         }
         }
 
 
         [Obsolete("This element has been renamed since version 2022.3. Please use the BeginPageNumberOfSection method.")]
         [Obsolete("This element has been renamed since version 2022.3. Please use the BeginPageNumberOfSection method.")]

+ 3 - 0
Source/QuestPDF/Infrastructure/IPageContext.cs

@@ -4,6 +4,7 @@ namespace QuestPDF.Infrastructure
 {
 {
     internal class DocumentLocation
     internal class DocumentLocation
     {
     {
+        public int DocumentId { get; set; }
         public string Name { get; set; }
         public string Name { get; set; }
         public int PageStart { get; set; }
         public int PageStart { get; set; }
         public int PageEnd { get; set; }
         public int PageEnd { get; set; }
@@ -12,8 +13,10 @@ namespace QuestPDF.Infrastructure
     
     
     internal interface IPageContext
     internal interface IPageContext
     {
     {
+        int DocumentLength { get; }
         int CurrentPage { get; }
         int CurrentPage { get; }
         void SetSectionPage(string name);
         void SetSectionPage(string name);
         DocumentLocation? GetLocation(string name);
         DocumentLocation? GetLocation(string name);
+        string GetDocumentLocationName(string locationName);
     }
     }
 }
 }

+ 16 - 4
Source/QuestPDF/Infrastructure/PageContext.cs

@@ -6,11 +6,17 @@ namespace QuestPDF.Infrastructure
 {
 {
     internal class PageContext : IPageContext
     internal class PageContext : IPageContext
     {
     {
-        public const string DocumentLocation = "document";
-        
+        public int DocumentLength { get; private set; }
         private List<DocumentLocation> Locations { get; } = new();
         private List<DocumentLocation> Locations { get; } = new();
+        
+        public int CurrentDocumentId { get; private set; }
         public int CurrentPage { get; private set; }
         public int CurrentPage { get; private set; }
 
 
+        internal void SetDocumentId(int id)
+        {
+            CurrentDocumentId = id;
+        }
+        
         internal void ResetPageNumber()
         internal void ResetPageNumber()
         {
         {
             CurrentPage = 0;
             CurrentPage = 0;
@@ -19,7 +25,7 @@ namespace QuestPDF.Infrastructure
         internal void IncrementPageNumber()
         internal void IncrementPageNumber()
         {
         {
             CurrentPage++;
             CurrentPage++;
-            SetSectionPage(DocumentLocation);
+            DocumentLength = Math.Max(DocumentLength, CurrentPage);
         }
         }
 
 
         public void SetSectionPage(string name)
         public void SetSectionPage(string name)
@@ -30,6 +36,7 @@ namespace QuestPDF.Infrastructure
             {
             {
                 location = new DocumentLocation
                 location = new DocumentLocation
                 {
                 {
+                    DocumentId = CurrentDocumentId,
                     Name = name,
                     Name = name,
                     PageStart = CurrentPage,
                     PageStart = CurrentPage,
                     PageEnd = CurrentPage
                     PageEnd = CurrentPage
@@ -44,7 +51,12 @@ namespace QuestPDF.Infrastructure
 
 
         public DocumentLocation? GetLocation(string name)
         public DocumentLocation? GetLocation(string name)
         {
         {
-            return Locations.Find(x => x.Name == name);
+            return Locations.Find(x => x.DocumentId == CurrentDocumentId && x.Name == name);
+        }
+        
+        public string GetDocumentLocationName(string locationName)
+        {
+            return $"{CurrentDocumentId} | {locationName}";
         }
         }
     }
     }
 }
 }