From a3ae684b556a8dd9463add3ed0e7d4a1f50c9cc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zi=C4=85bek?= Date: Tue, 21 Nov 2023 08:33:13 +0100 Subject: [PATCH] Shrink API (#722) * Shrink APIimplementation * Code refactoring * Improvements and fixes to the LayoutTestEngine * Updated Shrink API tests to the new approach * Fixed build --- .../QuestPDF.Examples/Engine/RenderingTest.cs | 2 +- .../QuestPDF.LayoutTests/LayoutTestResult.cs | 126 ----------------- Source/QuestPDF.LayoutTests/Setup.cs | 13 ++ Source/QuestPDF.LayoutTests/ShrinkTests.cs | 129 ++++++++++++++++++ .../TestEngine/FluentExtensions.cs | 18 ++- .../TestEngine/LayoutTest.cs | 26 ++-- .../TestEngine/LayoutTestExecutor.cs | 2 +- .../TestEngine/LayoutTestValidator.cs | 4 +- .../LayoutTestVisualizationStrategy.cs | 8 ++ .../TestEngine/MockChild.cs | 2 +- .../TestEngine/Settings.cs | 6 + .../TestEngine/WrapChild.cs | 18 +++ Source/QuestPDF.LayoutTests/Usings.cs | 5 +- Source/QuestPDF.UnitTests/BoxTests.cs | 94 ------------- .../Elements/{MinimalBox.cs => Shrink.cs} | 22 +-- Source/QuestPDF/Fluent/ElementExtensions.cs | 17 --- Source/QuestPDF/Fluent/GenerateExtensions.cs | 22 +-- Source/QuestPDF/Fluent/ShrinkExtensions.cs | 71 ++++++++++ Source/QuestPDF/Helpers/Helpers.cs | 15 ++ 19 files changed, 315 insertions(+), 285 deletions(-) delete mode 100644 Source/QuestPDF.LayoutTests/LayoutTestResult.cs create mode 100644 Source/QuestPDF.LayoutTests/Setup.cs create mode 100644 Source/QuestPDF.LayoutTests/ShrinkTests.cs create mode 100644 Source/QuestPDF.LayoutTests/TestEngine/LayoutTestVisualizationStrategy.cs create mode 100644 Source/QuestPDF.LayoutTests/TestEngine/Settings.cs create mode 100644 Source/QuestPDF.LayoutTests/TestEngine/WrapChild.cs delete mode 100644 Source/QuestPDF.UnitTests/BoxTests.cs rename Source/QuestPDF/Elements/{MinimalBox.cs => Shrink.cs} (56%) create mode 100644 Source/QuestPDF/Fluent/ShrinkExtensions.cs diff --git a/Source/QuestPDF.Examples/Engine/RenderingTest.cs b/Source/QuestPDF.Examples/Engine/RenderingTest.cs index 6a715ae1c..bffdd1703 100644 --- a/Source/QuestPDF.Examples/Engine/RenderingTest.cs +++ b/Source/QuestPDF.Examples/Engine/RenderingTest.cs @@ -121,7 +121,7 @@ public void Render(IDocument document) if (ShowResult && ShowingResultsEnabled) { var firstImagePath = fileNameSchema(0); - GenerateExtensions.OpenFileUsingDefaultProgram(firstImagePath); + Helpers.Helpers.OpenFileUsingDefaultProgram(firstImagePath); } } diff --git a/Source/QuestPDF.LayoutTests/LayoutTestResult.cs b/Source/QuestPDF.LayoutTests/LayoutTestResult.cs deleted file mode 100644 index e14747c71..000000000 --- a/Source/QuestPDF.LayoutTests/LayoutTestResult.cs +++ /dev/null @@ -1,126 +0,0 @@ -using QuestPDF.Fluent; -using QuestPDF.Infrastructure; -using QuestPDF.LayoutTests.TestEngine; - -namespace QuestPDF.LayoutTests; - -public class Tests -{ - [SetUp] - public void Setup() - { - } - - [Test] - public void Test1() - { - return; - - LayoutTest - .HavingSpaceOfSize(200, 400) - .WithContent(content => - { - content.Column(column => - { - column.Spacing(25); - - column.Item().Mock("a").Size(150, 200); - column.Item().Mock("b").Size(150, 150); - column.Item().Mock("c").Size(150, 100); - column.Item().Mock("d").Size(150, 150); - column.Item().Mock("e").Size(150, 300); - column.Item().Mock("f").Size(150, 150); - column.Item().Mock("g").Size(150, 100); - column.Item().Mock("h").Size(150, 500); - }); - }) - .ExpectedDrawResult(document => - { - document - .Page() - .TakenAreaSize(400, 300) - .Content(page => - { - page.Mock("a").Position(0, 0).Size(250, 200); - page.Mock("b").Position(150, 50).Size(50, 150); - page.Mock("c").Position(200, 100).Size(100, 50); - }); - - document - .Page() - .TakenAreaSize(400, 300) - .Content(page => - { - page.Mock("a").Position(0, 0).Size(150, 100); - page.Mock("b").Position(250, 150).Size(50, 150); - page.Mock("c").Position(300, 200).Size(100, 50); - }); - }); - //.CompareVisually(); - } - - [Test] - public void Test2() - { - LayoutTest - .HavingSpaceOfSize(200, 200) - .WithContent(content => - { - content.Column(column => - { - column.Spacing(25); - - column.Item().Mock("a").Size(150, 150); - column.Item().Mock("b").Size(125, 100); - }); - }) - .ExpectedDrawResult(document => - { - document - .Page() - .TakenAreaSize(150, 200) - .Content(page => - { - page.Mock("a").Position(0, 0).Size(150, 150); - page.Mock("b").Position(0, 175).Size(125, 25); - }); - - document - .Page() - .TakenAreaSize(125, 75) - .Content(page => - { - page.Mock("b").Position(0, 0).Size(125, 75); - }); - }); - } - - [Test] - public void Test3() - { - LayoutTest - .HavingSpaceOfSize(200, 200) - .WithContent(content => - { - content.Layers(layers => - { - layers.Layer().Mock("a").Size(100, 150); - layers.PrimaryLayer().Mock("b").Size(150, 100); - }); - }) - .ExpectedDrawResult(document => - { - document - .Page() - .TakenAreaSize(150, 100) - .Content(page => - { - page.Mock("b").Position(0, 0).Size(150, 100); - page.Mock("a").Position(0, 0).Size(100, 150); - - }); - - document.ExpectInfiniteLayoutException(); - }); - } -} \ No newline at end of file diff --git a/Source/QuestPDF.LayoutTests/Setup.cs b/Source/QuestPDF.LayoutTests/Setup.cs new file mode 100644 index 000000000..d2bedc774 --- /dev/null +++ b/Source/QuestPDF.LayoutTests/Setup.cs @@ -0,0 +1,13 @@ +namespace QuestPDF.LayoutTests +{ + [SetUpFixture] + public class Setup + { + [OneTimeSetUp] + public static void Configure() + { + QuestPDF.Settings.License = LicenseType.Community; + QuestPDF.LayoutTests.TestEngine.Settings.LayoutTestVisualizationStrategy = LayoutTestVisualizationStrategy.WhenFailure; + } + } +} \ No newline at end of file diff --git a/Source/QuestPDF.LayoutTests/ShrinkTests.cs b/Source/QuestPDF.LayoutTests/ShrinkTests.cs new file mode 100644 index 000000000..6ec5de28f --- /dev/null +++ b/Source/QuestPDF.LayoutTests/ShrinkTests.cs @@ -0,0 +1,129 @@ +namespace QuestPDF.LayoutTests; + +public class ShrinkTests +{ + [Test] + public void Both() + { + LayoutTest + .HavingSpaceOfSize(100, 120) + .WithContent(content => + { + content + .Shrink() + .Mock().Size(60, 200); + }) + .ExpectedDrawResult(document => + { + document + .Page() + .RequiredAreaSize(60, 120) + .Content(page => + { + page.Mock().Position(0, 0).Size(60, 120); + }); + + document + .Page() + .RequiredAreaSize(60, 80) + .Content(page => + { + page.Mock().Position(0, 0).Size(60, 80); + }); + }); + } + + [Test] + public void Vertical() + { + LayoutTest + .HavingSpaceOfSize(100, 120) + .WithContent(content => + { + content + .ShrinkVertical() + .Mock().Size(60, 200); + }) + .ExpectedDrawResult(document => + { + document + .Page() + .RequiredAreaSize(60, 120) + .Content(page => + { + page.Mock().Position(0, 0).Size(100, 120); + }); + + document + .Page() + .RequiredAreaSize(60, 80) + .Content(page => + { + page.Mock().Position(0, 0).Size(100, 80); + }); + }); + } + + [Test] + public void Horizontal() + { + LayoutTest + .HavingSpaceOfSize(100, 120) + .WithContent(content => + { + content + .ShrinkHorizontal() + .Mock().Size(60, 200); + }) + .ExpectedDrawResult(document => + { + document + .Page() + .RequiredAreaSize(60, 120) + .Content(page => + { + page.Mock().Position(0, 0).Size(60, 120); + }); + + document + .Page() + .RequiredAreaSize(60, 80) + .Content(page => + { + page.Mock().Position(0, 0).Size(60, 120); + }); + }); + } + + [Test] + public void ContentFromRightToLeft() + { + LayoutTest + .HavingSpaceOfSize(100, 120) + .WithContent(content => + { + content + .ContentFromRightToLeft() + .Shrink() + .Mock().Size(60, 200); + }) + .ExpectedDrawResult(document => + { + document + .Page() + .RequiredAreaSize(60, 120) + .Content(page => + { + page.Mock().Position(40, 0).Size(60, 120); + }); + + document + .Page() + .RequiredAreaSize(60, 80) + .Content(page => + { + page.Mock().Position(40, 0).Size(60, 80); + }); + }); + } +} \ No newline at end of file diff --git a/Source/QuestPDF.LayoutTests/TestEngine/FluentExtensions.cs b/Source/QuestPDF.LayoutTests/TestEngine/FluentExtensions.cs index 079bbd5ca..22448949a 100644 --- a/Source/QuestPDF.LayoutTests/TestEngine/FluentExtensions.cs +++ b/Source/QuestPDF.LayoutTests/TestEngine/FluentExtensions.cs @@ -29,7 +29,7 @@ public ExpectedPageLayoutDescriptor(LayoutTestResult.PageLayout pageLayout) PageLayout = pageLayout; } - public ExpectedPageLayoutDescriptor TakenAreaSize(float width, float height) + public ExpectedPageLayoutDescriptor RequiredAreaSize(float width, float height) { PageLayout.RequiredArea = new Size(width, height); return this; @@ -49,7 +49,7 @@ internal class ExpectedPageContentDescriptor { public List MockPositions { get;} = new(); - public ExpectedMockPositionDescriptor Mock(string mockId) + public ExpectedMockPositionDescriptor Mock(string mockId = MockFluent.DefaultMockId) { var child = new LayoutTestResult.MockLayoutPosition { MockId = mockId }; MockPositions.Add(child); @@ -79,9 +79,11 @@ public ExpectedMockPositionDescriptor Size(float width, float height) } } -internal static class ElementExtensions +internal static class MockFluent { - public static MockDescriptor Mock(this IContainer element, string id) + public const string DefaultMockId = "$mock"; + + public static MockDescriptor Mock(this IContainer element, string id = DefaultMockId) { var mock = new ElementMock { @@ -109,4 +111,12 @@ public MockDescriptor Size(float width, float height) return this; } +} + +internal static class WrapFluent +{ + public static void Wrap(this IContainer element) + { + element.Element(new WrapChild()); + } } \ No newline at end of file diff --git a/Source/QuestPDF.LayoutTests/TestEngine/LayoutTest.cs b/Source/QuestPDF.LayoutTests/TestEngine/LayoutTest.cs index cad8f8fc5..4ff0afc0b 100644 --- a/Source/QuestPDF.LayoutTests/TestEngine/LayoutTest.cs +++ b/Source/QuestPDF.LayoutTests/TestEngine/LayoutTest.cs @@ -43,18 +43,26 @@ public void ExpectedDrawResult(Action handler) TestResult.ExpectedLayout = builder.DocumentLayout; - GenerateTestPreview(); - LayoutTestValidator.Validate(TestResult); + try + { + LayoutTestValidator.Validate(TestResult); + } + catch + { + if (Settings.LayoutTestVisualizationStrategy != LayoutTestVisualizationStrategy.Never) + GenerateTestPreview(); + + throw; + } + finally + { + if (Settings.LayoutTestVisualizationStrategy == LayoutTestVisualizationStrategy.Always) + GenerateTestPreview(); + } } private void GenerateTestPreview() { - if (!Debugger.IsAttached) - { - Console.WriteLine("Debugger is not attached. Skipping test preview generation"); - return; - } - var path = Path.Combine(Path.GetTempPath(), $"{TestIdentifier}.pdf"); if (File.Exists(path)) @@ -64,6 +72,6 @@ private void GenerateTestPreview() LayoutTestResultVisualization.Visualize(TestResult, stream); stream.Dispose(); - Console.WriteLine($"Generated test case preview: {path}"); + Helpers.Helpers.OpenFileUsingDefaultProgram(path); } } diff --git a/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestExecutor.cs b/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestExecutor.cs index c27f61d7d..6f722e3f3 100644 --- a/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestExecutor.cs +++ b/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestExecutor.cs @@ -83,7 +83,7 @@ ICollection CollectMockInformation(ICollection x.PageNumber) .Select(x => new LayoutTestResult.PageLayout { - RequiredArea = pageSizes.ElementAt(x.Key - 1), + RequiredArea = pageSizes.ElementAt(x.Key), Mocks = x .Select(y => new LayoutTestResult.MockLayoutPosition { diff --git a/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestValidator.cs b/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestValidator.cs index 5cfd2dce1..96e61416e 100644 --- a/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestValidator.cs +++ b/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestValidator.cs @@ -40,10 +40,10 @@ public static void Validate(LayoutTestResult result) static void ValidatePage(LayoutTestResult.PageLayout actualLayout, LayoutTestResult.PageLayout expectedLayout) { if (Math.Abs(actualLayout.RequiredArea.Width - expectedLayout.RequiredArea.Width) > Size.Epsilon) - throw new LayoutTestException($"Taken horizontal area is equal to {actualLayout.RequiredArea.Width} but expected {expectedLayout.RequiredArea.Width}"); + throw new LayoutTestException($"Required horizontal area is equal to {actualLayout.RequiredArea.Width} but expected {expectedLayout.RequiredArea.Width}"); if (Math.Abs(actualLayout.RequiredArea.Height - expectedLayout.RequiredArea.Height) > Size.Epsilon) - throw new LayoutTestException($"Taken vertical area is equal to {actualLayout.RequiredArea.Height} but expected {expectedLayout.RequiredArea.Height}"); + throw new LayoutTestException($"Required vertical area is equal to {actualLayout.RequiredArea.Height} but expected {expectedLayout.RequiredArea.Height}"); if (actualLayout.Mocks.Count != expectedLayout.Mocks.Count) throw new LayoutTestException($"Visible {actualLayout.Mocks.Count} mocks but expected {expectedLayout.Mocks.Count}"); diff --git a/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestVisualizationStrategy.cs b/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestVisualizationStrategy.cs new file mode 100644 index 000000000..c338a7194 --- /dev/null +++ b/Source/QuestPDF.LayoutTests/TestEngine/LayoutTestVisualizationStrategy.cs @@ -0,0 +1,8 @@ +namespace QuestPDF.LayoutTests.TestEngine; + +public enum LayoutTestVisualizationStrategy +{ + Never, + WhenFailure, + Always +} \ No newline at end of file diff --git a/Source/QuestPDF.LayoutTests/TestEngine/MockChild.cs b/Source/QuestPDF.LayoutTests/TestEngine/MockChild.cs index 170c66271..ae44f0aae 100644 --- a/Source/QuestPDF.LayoutTests/TestEngine/MockChild.cs +++ b/Source/QuestPDF.LayoutTests/TestEngine/MockChild.cs @@ -61,7 +61,7 @@ internal override void Draw(Size availableSpace) MockId = MockId, PageNumber = PageContext.CurrentPage, Position = new Position(matrix.TransX / matrix.ScaleX, matrix.TransY / matrix.ScaleY), - Size = size + Size = availableSpace }); } } \ No newline at end of file diff --git a/Source/QuestPDF.LayoutTests/TestEngine/Settings.cs b/Source/QuestPDF.LayoutTests/TestEngine/Settings.cs new file mode 100644 index 000000000..eba30374f --- /dev/null +++ b/Source/QuestPDF.LayoutTests/TestEngine/Settings.cs @@ -0,0 +1,6 @@ +namespace QuestPDF.LayoutTests.TestEngine; + +public static class Settings +{ + public static LayoutTestVisualizationStrategy LayoutTestVisualizationStrategy { get; set; } = LayoutTestVisualizationStrategy.WhenFailure; +} \ No newline at end of file diff --git a/Source/QuestPDF.LayoutTests/TestEngine/WrapChild.cs b/Source/QuestPDF.LayoutTests/TestEngine/WrapChild.cs new file mode 100644 index 000000000..9afb34ac3 --- /dev/null +++ b/Source/QuestPDF.LayoutTests/TestEngine/WrapChild.cs @@ -0,0 +1,18 @@ +using QuestPDF.Drawing; +using QuestPDF.Helpers; +using QuestPDF.Infrastructure; + +namespace QuestPDF.LayoutTests.TestEngine; + +internal class WrapChild : Element +{ + internal override SpacePlan Measure(Size availableSpace) + { + return SpacePlan.Wrap(); + } + + internal override void Draw(Size availableSpace) + { + + } +} \ No newline at end of file diff --git a/Source/QuestPDF.LayoutTests/Usings.cs b/Source/QuestPDF.LayoutTests/Usings.cs index cefced496..c6cd351ba 100644 --- a/Source/QuestPDF.LayoutTests/Usings.cs +++ b/Source/QuestPDF.LayoutTests/Usings.cs @@ -1 +1,4 @@ -global using NUnit.Framework; \ No newline at end of file +global using NUnit.Framework; +global using QuestPDF.Fluent; +global using QuestPDF.Infrastructure; +global using QuestPDF.LayoutTests.TestEngine; \ No newline at end of file diff --git a/Source/QuestPDF.UnitTests/BoxTests.cs b/Source/QuestPDF.UnitTests/BoxTests.cs deleted file mode 100644 index 85d976368..000000000 --- a/Source/QuestPDF.UnitTests/BoxTests.cs +++ /dev/null @@ -1,94 +0,0 @@ -using NUnit.Framework; -using QuestPDF.Drawing; -using QuestPDF.Elements; -using QuestPDF.Infrastructure; -using QuestPDF.UnitTests.TestEngine; - -namespace QuestPDF.UnitTests -{ - [TestFixture] - public class BoxTests - { - [Test] - public void Measure() => SimpleContainerTests.Measure(); - - [Test] - public void Draw_Wrap() - { - TestPlan - .For(x => new MinimalBox - { - Child = x.CreateChild() - }) - .DrawElement(new Size(400, 300)) - .ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.Wrap()) - .CheckDrawResult(); - } - - [Test] - public void Measure_PartialRender() - { - TestPlan - .For(x => new MinimalBox - { - Child = x.CreateChild() - }) - .MeasureElement(new Size(400, 300)) - .ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.PartialRender(200, 100)) - .ExpectCanvasTranslate(0, 0) - .ExpectChildDraw(new Size(200, 100)) - .ExpectCanvasTranslate(0, 0) - .CheckDrawResult(); - } - - [Test] - public void Measure_FullRender() - { - TestPlan - .For(x => new MinimalBox - { - Child = x.CreateChild() - }) - .MeasureElement(new Size(500, 400)) - .ExpectChildMeasure(expectedInput: new Size(500, 400), returns: SpacePlan.FullRender(300, 200)) - .ExpectCanvasTranslate(0, 0) - .ExpectChildDraw(new Size(300, 200)) - .ExpectCanvasTranslate(0, 0) - .CheckDrawResult(); - } - - [Test] - public void Measure_PartialRender_RightToLeft() - { - TestPlan - .For(x => new MinimalBox - { - Child = x.CreateChild(), - ContentDirection = ContentDirection.RightToLeft - }) - .MeasureElement(new Size(400, 300)) - .ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.PartialRender(200, 100)) - .ExpectCanvasTranslate(200, 0) - .ExpectChildDraw(new Size(200, 100)) - .ExpectCanvasTranslate(-200, 0) - .CheckDrawResult(); - } - - [Test] - public void Measure_FullRender_RightToLeft() - { - TestPlan - .For(x => new MinimalBox - { - Child = x.CreateChild(), - ContentDirection = ContentDirection.RightToLeft - }) - .MeasureElement(new Size(500, 400)) - .ExpectChildMeasure(expectedInput: new Size(500, 400), returns: SpacePlan.FullRender(350, 200)) - .ExpectCanvasTranslate(150, 0) - .ExpectChildDraw(new Size(350, 200)) - .ExpectCanvasTranslate(-150, 0) - .CheckDrawResult(); - } - } -} \ No newline at end of file diff --git a/Source/QuestPDF/Elements/MinimalBox.cs b/Source/QuestPDF/Elements/Shrink.cs similarity index 56% rename from Source/QuestPDF/Elements/MinimalBox.cs rename to Source/QuestPDF/Elements/Shrink.cs index dc936edf0..fec27b986 100644 --- a/Source/QuestPDF/Elements/MinimalBox.cs +++ b/Source/QuestPDF/Elements/Shrink.cs @@ -1,23 +1,27 @@ -using QuestPDF.Drawing; +using QuestPDF.Drawing; using QuestPDF.Infrastructure; namespace QuestPDF.Elements { - internal sealed class MinimalBox : ContainerElement, IContentDirectionAware + internal class Shrink : ContainerElement, IContentDirectionAware { - public ContentDirection ContentDirection { get; set; } + public bool Vertical { get; set; } + public bool Horizontal { get; set; } + public ContentDirection ContentDirection { get; set; } + internal override void Draw(Size availableSpace) { - var targetSize = base.Measure(availableSpace); - - if (targetSize.Type == SpacePlanType.Wrap) - return; - + var childSize = base.Measure(availableSpace); + + var targetSize = new Size( + Horizontal ? childSize.Width : availableSpace.Width, + Vertical ? childSize.Height : availableSpace.Height); + var translate = ContentDirection == ContentDirection.RightToLeft ? new Position(availableSpace.Width - targetSize.Width, 0) : Position.Zero; - + Canvas.Translate(translate); base.Draw(targetSize); Canvas.Translate(translate.Reverse()); diff --git a/Source/QuestPDF/Fluent/ElementExtensions.cs b/Source/QuestPDF/Fluent/ElementExtensions.cs index 4bcaf157b..e0eea2f81 100644 --- a/Source/QuestPDF/Fluent/ElementExtensions.cs +++ b/Source/QuestPDF/Fluent/ElementExtensions.cs @@ -300,23 +300,6 @@ public static void Canvas(this IContainer element, DrawOnCanvas handler) }); } - [Obsolete("This element has been renamed since version 2022.1. Please use the MinimalBox method.")] - public static IContainer Box(this IContainer element) - { - return element.Element(new MinimalBox()); - } - - /// - /// Renders its content in the most compact size achievable. - /// Ideal for situations where the parent element provides more space than necessary. - ///
- /// Learn more - ///
- public static IContainer MinimalBox(this IContainer element) - { - return element.Element(new MinimalBox()); - } - /// /// Removes size constraints and grants its content virtually unlimited space. /// Learn more diff --git a/Source/QuestPDF/Fluent/GenerateExtensions.cs b/Source/QuestPDF/Fluent/GenerateExtensions.cs index 7728ed66c..88d216948 100644 --- a/Source/QuestPDF/Fluent/GenerateExtensions.cs +++ b/Source/QuestPDF/Fluent/GenerateExtensions.cs @@ -49,7 +49,7 @@ public static void GeneratePdfAndShow(this IDocument document) var filePath = Path.Combine(Path.GetTempPath(), $"QuestPDF Document {GenerateAndShowCounter}.pdf"); document.GeneratePdf(filePath); - OpenFileUsingDefaultProgram(filePath); + Helpers.Helpers.OpenFileUsingDefaultProgram(filePath); } #endregion @@ -92,7 +92,7 @@ public static void GenerateXpsAndShow(this IDocument document) var filePath = Path.Combine(Path.GetTempPath(), $"QuestPDF Document {GenerateAndShowCounter}.xps"); document.GenerateXps(filePath); - OpenFileUsingDefaultProgram(filePath); + Helpers.Helpers.OpenFileUsingDefaultProgram(filePath); } #endregion @@ -137,23 +137,5 @@ public static void GenerateImages(this IDocument document, GenerateDocumentImage } #endregion - - #region Helpers - - internal static void OpenFileUsingDefaultProgram(string filePath) - { - var process = new Process - { - StartInfo = new ProcessStartInfo(filePath) - { - UseShellExecute = true - } - }; - - process.Start(); - process.WaitForExit(); - } - - #endregion } } \ No newline at end of file diff --git a/Source/QuestPDF/Fluent/ShrinkExtensions.cs b/Source/QuestPDF/Fluent/ShrinkExtensions.cs new file mode 100644 index 000000000..5ba029311 --- /dev/null +++ b/Source/QuestPDF/Fluent/ShrinkExtensions.cs @@ -0,0 +1,71 @@ +using System; +using QuestPDF.Elements; +using QuestPDF.Infrastructure; + +namespace QuestPDF.Fluent +{ + public static class ShrinkExtensions + { + private static IContainer Shrink(this IContainer element, bool? vertical = null, bool? horizontal = null) + { + var shrink = element as Shrink ?? new Shrink(); + + if (vertical.HasValue) + shrink.Vertical = vertical.Value; + + if (horizontal.HasValue) + shrink.Horizontal = horizontal.Value; + + return element.Element(shrink); + } + + /// + /// Renders its content in the most compact size achievable. + /// Ideal for situations where the parent element provides more space than necessary. + ///
+ /// Learn more + ///
+ public static IContainer Shrink(this IContainer element) + { + return element.Shrink(vertical: true, horizontal: true); + } + + /// + /// Minimizes content height to the minimum, optimizing vertical space. + /// Ideal for situations where the parent element provides more space than necessary. + ///
+ /// Learn more + ///
+ public static IContainer ShrinkVertical(this IContainer element) + { + return element.Shrink(vertical: true); + } + + /// + /// Minimizes content width to the minimum, optimizing horizontal space. + /// Ideal for situations where the parent element provides more space than necessary. + ///
+ /// Learn more + ///
+ public static IContainer ShrinkHorizontal(this IContainer element) + { + return element.Shrink(horizontal: true); + } + + #region Obsolete + + [Obsolete("This element has been renamed since version 2022.1. Please use the Shrink method.")] + public static IContainer Box(this IContainer element) + { + return element.Shrink(); + } + + [Obsolete("This element has been renamed since version 2023.11. Please use the Shrink method.")] + public static IContainer MinimalBox(this IContainer element) + { + return element.Shrink(); + } + + #endregion + } +} \ No newline at end of file diff --git a/Source/QuestPDF/Helpers/Helpers.cs b/Source/QuestPDF/Helpers/Helpers.cs index 2b8fc9e5b..7b405ac5b 100644 --- a/Source/QuestPDF/Helpers/Helpers.cs +++ b/Source/QuestPDF/Helpers/Helpers.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; @@ -129,5 +130,19 @@ internal static SKImage GetImageWithSmallerSize(SKImage one, SKImage second) ? one : second; } + + internal static void OpenFileUsingDefaultProgram(string filePath) + { + var process = new Process + { + StartInfo = new ProcessStartInfo(filePath) + { + UseShellExecute = true + } + }; + + process.Start(); + process.WaitForExit(); + } } } \ No newline at end of file