Browse Source

Improved layout stability of the EnsureSpace element

Marcin Ziąbek 9 months ago
parent
commit
64e36642fc

+ 16 - 5
Source/QuestPDF/Elements/EnsureSpace.cs

@@ -5,7 +5,8 @@ namespace QuestPDF.Elements
 {
 {
     internal sealed class EnsureSpace : ContainerElement, IStateful
     internal sealed class EnsureSpace : ContainerElement, IStateful
     {
     {
-        public float? MinHeight { get; set; } = null;
+        public const float DefaultMinHeight = 150;
+        public float MinHeight { get; set; } = DefaultMinHeight;
 
 
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
@@ -17,19 +18,29 @@ namespace QuestPDF.Elements
             if (measurement.Type != SpacePlanType.PartialRender)
             if (measurement.Type != SpacePlanType.PartialRender)
                 return measurement;
                 return measurement;
 
 
-            if (MinHeight == null || MinHeight <= availableSpace.Height)
+            if (MinHeight <= measurement.Height)
                 return measurement;
                 return measurement;
             
             
-            return SpacePlan.Wrap("The available vertical space is smaller than requested in the constraint.");
+            return SpacePlan.PartialRender(Size.Zero);
         }
         }
         
         
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)
         {
         {
-            base.Draw(availableSpace);
+            if (IsFirstPageRendered)
+            {
+                base.Draw(availableSpace);
+                return;
+            }
+
+            var measurement = base.Measure(availableSpace);
+            
+            if (MinHeight <= measurement.Height)
+                base.Draw(availableSpace);
+            
             IsFirstPageRendered = true;
             IsFirstPageRendered = true;
         }
         }
 
 
-        internal override string? GetCompanionHint() => MinHeight.HasValue ? $"at least {MinHeight.Value}" : null;
+        internal override string? GetCompanionHint() => $"at least {MinHeight}";
         
         
         #region IStateful
         #region IStateful
         
         

+ 15 - 8
Source/QuestPDF/Fluent/ElementExtensions.cs

@@ -213,19 +213,26 @@ namespace QuestPDF.Fluent
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// <para>Serves as a less-strict approach compared to the <see cref="ElementExtensions.ShowEntire">ShowEntire</see> element.</para>
         /// <para>
         /// <para>
-        /// It impacts only the very first page of its content's occurence.
-        /// If the element fits within its first page, it's rendered as usual.
-        /// However, if the element doesn't fit and the available space has less vertical space than required height, the content is entirely shifted to the next page.
+        /// Ensures that the container's content occupies at least a specified minimum height on its first page of occurrence.
+        /// If there is enough space, the content is rendered as usual. However, if a page break is required,
+        /// this method ensures that a minimum amount of space is available before rendering the content.
+        /// If the required space is not available, the content is moved to the next page.
+        /// </para>
+        /// <para>
+        /// This rule applies only to the first page where the content appears. If the content spans multiple pages,
+        /// all subsequent pages are rendered without this restriction. 
+        /// </para>
+        /// <para>
+        /// This method is particularly useful for structured elements like tables, where rendering only a small fragment 
+        /// at the bottom of a page could negatively impact readability. By ensuring a minimum height, 
+        /// you can prevent undesired content fragmentation.
         /// </para>
         /// </para>
         /// <br />
         /// <br />
         /// <a href="https://www.questpdf.com/api-reference/ensure-space.html">Learn more</a>
         /// <a href="https://www.questpdf.com/api-reference/ensure-space.html">Learn more</a>
         /// </summary>
         /// </summary>
-        /// <remarks>
-        /// This is especially useful for elements like tables, where you'd want to display several rows together. By setting the minHeight, you can avoid scenarios where only a single row appears at the page's end, ensuring a more cohesive presentation.
-        /// </remarks>
-        public static IContainer EnsureSpace(this IContainer element, float? minHeight = null)
+        /// <param name="minHeight">The minimum height, in points, that the element should occupy before a page break.</param>
+        public static IContainer EnsureSpace(this IContainer element, float minHeight = Elements.EnsureSpace.DefaultMinHeight)
         {
         {
             return element.Element(new EnsureSpace
             return element.Element(new EnsureSpace
             {
             {