Răsfoiți Sursa

Code refactoring

Marcin Ziąbek 1 an în urmă
părinte
comite
e59d23ec05

+ 3 - 2
Source/QuestPDF/Drawing/DocumentGenerator.cs

@@ -251,7 +251,7 @@ namespace QuestPDF.Drawing
                 overflowState.CaptureOriginalMeasurementValues();
                 overflowState.ApplyLayoutOverflowVisualization();
 
-                var rootCause = overflowState.FindElementOfType<LayoutOverflowVisualization>();
+                var rootCause = overflowState.FindLayoutOverflowVisualizationNodes().First();
                 
                 var stack = rootCause
                     .ExtractAncestors()
@@ -276,7 +276,8 @@ namespace QuestPDF.Drawing
                     $"The library will generate a PDF document with visually annotated places where layout constraints are invalid. {newParagraph}" +
                     $"Alternatively, if you don’t want to or cannot attach the debugger, you can set the {nameof(QuestPDF)}.{nameof(Settings)}.{nameof(Settings.EnableDebugging)} flag to true. {newParagraph}" +
                     $"The layout issue is likely present in the following part of the document: {newParagraph}{stack}{newParagraph}" +
-                    $"Please analyse the document measurement to learn more: {newParagraph}{inside}";
+                    $"Please analyse the document measurement to learn more: {newParagraph}{inside}" +
+                    $"{LayoutDebugging.LayoutVisualizationLegend}";
                 
                 throw new DocumentLayoutException(message);
             }

+ 36 - 7
Source/QuestPDF/Drawing/Proxy/LayoutDebugging.cs

@@ -153,6 +153,22 @@ internal static class LayoutDebugging
             CaptureOriginalMeasurementValues(child);
     }
     
+    public static IEnumerable<TreeNode<OverflowDebuggingProxy>> FindLayoutOverflowVisualizationNodes(this TreeNode<OverflowDebuggingProxy> rootNode)
+    {
+        var result = new List<TreeNode<OverflowDebuggingProxy>>();
+        Traverse(rootNode);
+        return result;
+        
+        void Traverse(TreeNode<OverflowDebuggingProxy> node)
+        {
+            if (node.Value.Child is LayoutOverflowVisualization)
+                result.Add(node);
+
+            foreach (var child in node.Children)
+                Traverse(child);
+        }
+    }
+    
     public static string FormatAncestors(this IEnumerable<OverflowDebuggingProxy> ancestors)
     {
         var result = new StringBuilder();
@@ -230,30 +246,36 @@ internal static class LayoutDebugging
             
             if (child is LayoutOverflowVisualization layoutOverflowVisualization)
                 child = layoutOverflowVisualization.Child;
+
+            var title = GetTitle();
+            yield return title;
             
-            yield return $"{SpacePlanDot()} {child.GetType().Name}";
-            
-            yield return new string('=', child.GetType().Name.Length + 4);
+            yield return new string('=', title.Length + 1);
             
             yield return $"Available Space: {proxy.OriginalMeasurementSize}";
             yield return $"Space Plan: {proxy.OriginalSpacePlan}";
             
-            yield return new string('-', child.GetType().Name.Length + 4);
+            yield return new string('-', title.Length + 1);
             
             foreach (var configuration in GetElementConfiguration(child))
                 yield return $"{configuration}";
             
-            string SpacePlanDot()
+            string GetTitle()
             {
-                var issueIndicator = "🚨"; 
+                var elementName = child.GetType().Name;
                 
-                return proxy.OriginalSpacePlan.Value.Type switch
+                if (proxy.Child is LayoutOverflowVisualization)
+                    return $"🚨 {elementName} 🚨";
+                
+                var indicator = proxy.OriginalSpacePlan.Value.Type switch
                 {
                     SpacePlanType.Wrap => "🔴",
                     SpacePlanType.PartialRender => "🟡",
                     SpacePlanType.FullRender => "🟢",
                     _ => "-"
                 };
+                
+                return $"{indicator} {elementName}";
             }
         }
         
@@ -288,4 +310,11 @@ internal static class LayoutDebugging
             }
         }
     }
+    
+    public const string LayoutVisualizationLegend =
+        "Legend: \n" +
+        "🚨 - Element that is likely the root cause of the layout issue based on library heuristics and prediction. \n" +
+        "🔴 - Element that cannot be drawn due to the provided layout constraints. This element likely causes the layout issue, or one of its descendant children is responsible for the problem. \n" +
+        "🟡 - Element that can be partially drawn on the page and will also be rendered on the consecutive page. In more complex layouts, this element may also cause issues or contain a child that is the actual root cause.\n" +
+        "🟢 - Element that is successfully and completely drawn on the page.\n";
 }

+ 7 - 27
Source/QuestPDF/Drawing/Proxy/TreeTraversal.cs

@@ -48,36 +48,16 @@ internal static class TreeTraversal
                 yield return innerChild;
     }
     
-    public static ICollection<TreeNode<T>> ExtractAncestors<T>(this TreeNode<T> element)
+    public static IEnumerable<TreeNode<T>> ExtractAncestors<T>(this TreeNode<T> node)
     {
-        var parent = element;
-        var result = new List<TreeNode<T>>();
-        
-        while (parent is not null)
+        while (true)
         {
-            result.Add(parent);
-            parent = parent.Parent;
-        }
-
-        return result;
-    }
-    
-    public static TreeNode<OverflowDebuggingProxy>? FindElementOfType<TChild>(this TreeNode<OverflowDebuggingProxy> element)
-    {
-        TreeNode<OverflowDebuggingProxy> result = null;
-        Traverse(element);
-        return result;
-        
-        void Traverse(TreeNode<OverflowDebuggingProxy> currentElement)
-        {
-            if (currentElement.Value.Child is TChild)
-            {
-                result = currentElement;
-                return;
-            }
+            node = node.Parent;
+            
+            if (node is null)
+                yield break;
 
-            foreach (var child in currentElement.Children)
-                Traverse(child);
+            yield return node;
         }
     }
 }