diff --git a/QuestPDF.Examples/ElementExamples.cs b/QuestPDF.Examples/ElementExamples.cs index 22e7626..8cdd148 100644 --- a/QuestPDF.Examples/ElementExamples.cs +++ b/QuestPDF.Examples/ElementExamples.cs @@ -17,7 +17,7 @@ namespace QuestPDF.Examples .Placeholder(); } - //[ShowResult] + [ShowResult] [ImageSize(300, 300)] public void Section(IContainer container) { @@ -167,7 +167,7 @@ namespace QuestPDF.Examples }); } - [ShowResult] + //[ShowResult] [ImageSize(300, 200)] public void GridExample(IContainer container) { diff --git a/QuestPDF.UnitTests/AlignmentTests.cs b/QuestPDF.UnitTests/AlignmentTests.cs index 1e623f1..93cb535 100644 --- a/QuestPDF.UnitTests/AlignmentTests.cs +++ b/QuestPDF.UnitTests/AlignmentTests.cs @@ -15,19 +15,6 @@ namespace QuestPDF.UnitTests [Test] public void Draw_ShouldHandleNullChild() => new Alignment().DrawWithoutChild(); - [Test] - public void Measure_ShouldReturnWrap_WhenChildReturnsWrap() - { - TestPlan - .For(x => new Alignment - { - Child = x.CreateChild() - }) - .MeasureElement(new Size(1000, 500)) - .ExpectChildMeasure(expectedInput: new Size(1000, 500), returns: new Wrap()) - .CheckMeasureResult(new Wrap()); - } - [Test] public void Draw_HorizontalCenter_VerticalCenter() { diff --git a/QuestPDF/Elements/Decoration.cs b/QuestPDF/Elements/Decoration.cs new file mode 100644 index 0000000..52a0562 --- /dev/null +++ b/QuestPDF/Elements/Decoration.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using QuestPDF.Drawing.SpacePlan; +using QuestPDF.Infrastructure; + +namespace QuestPDF.Elements +{ + internal enum DecorationType + { + Prepend, + Append + } + + internal class Decoration : Element + { + public Element? DecorationElement { get; set; } + public Element? ContentElement { get; set; } + public DecorationType Type { get; set; } + + internal override ISpacePlan Measure(Size availableSpace) + { + var decorationMeasure = DecorationElement?.Measure(availableSpace); + + if (decorationMeasure is Wrap || decorationMeasure is PartialRender) + return new Wrap(); + + var decorationSize = decorationMeasure as Size ?? Size.Zero; + var contentMeasure = ContentElement?.Measure(new Size(availableSpace.Width, availableSpace.Height - decorationSize.Height)) ?? new FullRender(Size.Zero); + + if (contentMeasure is Wrap) + return new Wrap(); + + var contentSize = contentMeasure as Size ?? Size.Zero; + var resultSize = new Size(availableSpace.Width, decorationSize.Height + contentSize.Height); + + if (contentSize is PartialRender) + return new PartialRender(resultSize); + + if (contentSize is FullRender) + return new FullRender(resultSize); + + throw new NotSupportedException(); + } + + internal override void Draw(ICanvas canvas, Size availableSpace) + { + var decorationSize = DecorationElement?.Measure(availableSpace) as Size ?? Size.Zero; + var contentSize = new Size(availableSpace.Width, availableSpace.Height - decorationSize.Height); + + var translateHeight = Type == DecorationType.Prepend ? decorationSize.Height : contentSize.Height; + Action drawDecoration = () => DecorationElement?.Draw(canvas, new Size(availableSpace.Width, decorationSize.Height)); + Action drawContent = () => ContentElement?.Draw(canvas, new Size (availableSpace.Width, contentSize.Height)); + + var first = Type == DecorationType.Prepend ? drawDecoration : drawContent; + var second = Type == DecorationType.Prepend ? drawContent : drawDecoration; + + first(); + canvas.Translate(new Position(0, translateHeight)); + second(); + canvas.Translate(new Position(0, -translateHeight)); + } + } +} \ No newline at end of file diff --git a/QuestPDF/Elements/Grid.cs b/QuestPDF/Elements/Grid.cs index bc67068..6c1c06a 100644 --- a/QuestPDF/Elements/Grid.cs +++ b/QuestPDF/Elements/Grid.cs @@ -15,7 +15,8 @@ namespace QuestPDF.Elements public int ColumnsCount { get; set; } = DefaultColumnsCount; public HorizontalAlignment Alignment { get; set; } = Left; - public float Spacing { get; set; } = 0; + public float VerticalSpacing { get; set; } = 0; + public float HorizontalSpacing { get; set; } = 0; public void Compose(IContainer container) { @@ -23,7 +24,7 @@ namespace QuestPDF.Elements container.Stack(stack => { - stack.Spacing(Spacing); + stack.Spacing(HorizontalSpacing); while (ChildrenQueue.Any()) stack.Element().Row(BuildRow); @@ -48,7 +49,7 @@ namespace QuestPDF.Elements void BuildRow(RowDescriptor row) { - row.Spacing(Spacing); + row.Spacing(HorizontalSpacing); var elements = GetRowElements().ToList(); var columnsWidth = elements.Sum(x => x.Columns); diff --git a/QuestPDF/Elements/Page.cs b/QuestPDF/Elements/Page.cs index 8e34553..2e626f0 100644 --- a/QuestPDF/Elements/Page.cs +++ b/QuestPDF/Elements/Page.cs @@ -1,57 +1,24 @@ using System; using QuestPDF.Drawing.SpacePlan; +using QuestPDF.Fluent; using QuestPDF.Infrastructure; namespace QuestPDF.Elements { - internal class Page : Element + internal class Page : IComponent { public Element? Header { get; set; } public Element? Content { get; set; } public Element? Footer { get; set; } - - internal override ISpacePlan Measure(Size availableSpace) + + public void Compose(IContainer container) { - var headerSize = Header?.Measure(availableSpace) as Size; - var footerSize = Footer?.Measure(availableSpace) as Size; - - var contentHeight = availableSpace.Height - (headerSize?.Height ?? 0) - (footerSize?.Height ?? 0); - - var required = Content.Measure(new Size(availableSpace.Width, contentHeight)); - - if (required is FullRender) - return new FullRender(availableSpace); - - if (required is PartialRender) - return new PartialRender(availableSpace); - - if (required is Wrap) - return new Wrap(); - - throw new NotSupportedException(); - } - - internal override void Draw(ICanvas canvas, Size availableSpace) - { - var headerHeight = (Header?.Measure(availableSpace) as Size)?.Height ?? 0; - var footerHeight = (Footer?.Measure(availableSpace) as Size)?.Height ?? 0; - - var contentHeight = availableSpace.Height - headerHeight - footerHeight; - var contentSize = new Size(availableSpace.Width, contentHeight); - - if (headerHeight > 0) + container.Section(section => { - Header?.Draw(canvas, new Size(availableSpace.Width, headerHeight)); - canvas.Translate(new Position(0, headerHeight)); - } - - Content.Draw(canvas, new Size(availableSpace.Width, contentSize.Height)); - canvas.Translate(new Position(0, contentSize.Height)); - - if (footerHeight > 0) - { - Footer?.Draw(canvas, new Size(availableSpace.Width, footerHeight)); - } + section.Header().Element(Header ?? new Empty()); + section.Content().Extend().Element(Content ?? new Empty()); + section.Footer().Element(Footer ?? new Empty()); + }); } } } \ No newline at end of file diff --git a/QuestPDF/Elements/Section.cs b/QuestPDF/Elements/Section.cs index 40ee47b..aece345 100644 --- a/QuestPDF/Elements/Section.cs +++ b/QuestPDF/Elements/Section.cs @@ -1,62 +1,29 @@ using System; using QuestPDF.Drawing.SpacePlan; +using QuestPDF.Fluent; using QuestPDF.Infrastructure; namespace QuestPDF.Elements { - internal class Section : Element + internal class Section : IComponent { - public ContainerElement? Header { get; set; } - public ContainerElement? Content { get; set; } + public Element Header { get; set; } = new Empty(); + public Element Content { get; set; } = new Empty(); + public Element Footer { get; set; } = new Empty(); - internal override ISpacePlan Measure(Size availableSpace) + public void Compose(IContainer container) { - var headerMeasure = Header?.Measure(availableSpace); - - if (headerMeasure is Wrap || headerMeasure is PartialRender) - return new Wrap(); - - var headerSize = headerMeasure as Size ?? Size.Zero; - var contentMeasure = Content?.Measure(new Size(availableSpace.Width, availableSpace.Height - headerSize.Height)) ?? new FullRender(Size.Zero); - - if (contentMeasure is Wrap) - return new Wrap(); - - var contentSize = contentMeasure as Size ?? Size.Zero; - - var newSize = new Size( - availableSpace.Width, - headerSize.Height + contentSize.Height); - - if (contentSize is PartialRender) - return new PartialRender(newSize); - - if (contentSize is FullRender) - return new FullRender(newSize); - - throw new NotSupportedException(); - } - - internal override void Draw(ICanvas canvas, Size availableSpace) - { - var measurement = Measure(availableSpace); - - if (measurement is Wrap) - return; - - var headerSize = Header?.Measure(availableSpace) as Size ?? Size.Zero; - - var contentAvailableSize = new Size(availableSpace.Width, availableSpace.Height - headerSize.Height); - var contentSize = Content?.Measure(contentAvailableSize) as Size; - - Header?.Draw(canvas, new Size(availableSpace.Width, headerSize.Height)); - - canvas.Translate(new Position(0, headerSize.Height)); - - if (contentSize != null) - Content?.Draw(canvas, new Size(availableSpace.Width, contentSize.Height)); - - canvas.Translate(new Position(0, -headerSize.Height)); + container.Element(new Decoration + { + Type = DecorationType.Prepend, + DecorationElement = Header, + ContentElement = new Decoration + { + Type = DecorationType.Append, + ContentElement = Content, + DecorationElement = Footer + } + }); } } } \ No newline at end of file diff --git a/QuestPDF/Fluent/GridExtensions.cs b/QuestPDF/Fluent/GridExtensions.cs index e3f122d..d933572 100644 --- a/QuestPDF/Fluent/GridExtensions.cs +++ b/QuestPDF/Fluent/GridExtensions.cs @@ -11,7 +11,18 @@ namespace QuestPDF.Fluent public void Spacing(float value) { - Grid.Spacing = value; + VerticalSpacing(value); + HorizontalSpacing(value); + } + + public void VerticalSpacing(float value) + { + Grid.VerticalSpacing = value; + } + + public void HorizontalSpacing(float value) + { + Grid.HorizontalSpacing = value; } public void Columns(int value = Grid.DefaultColumnsCount) diff --git a/QuestPDF/Fluent/PageExtensions.cs b/QuestPDF/Fluent/PageExtensions.cs index 3248cf1..3a434d0 100644 --- a/QuestPDF/Fluent/PageExtensions.cs +++ b/QuestPDF/Fluent/PageExtensions.cs @@ -6,13 +6,8 @@ namespace QuestPDF.Fluent { public class PageDescriptor { - private Page Page { get; } - - internal PageDescriptor(Page page) - { - Page = page; - } - + internal Page Page { get; } = new Page(); + public IContainer Header() { var container = new Container(); @@ -54,11 +49,9 @@ namespace QuestPDF.Fluent { public static void Page(this IContainer document, Action handler) { - var page = new Page(); - document.Element(page); - - var descriptor = new PageDescriptor(page); + var descriptor = new PageDescriptor(); handler(descriptor); + document.Component(descriptor.Page); } } } \ No newline at end of file diff --git a/QuestPDF/Fluent/SectionExtensions.cs b/QuestPDF/Fluent/SectionExtensions.cs index d10a5a5..515b881 100644 --- a/QuestPDF/Fluent/SectionExtensions.cs +++ b/QuestPDF/Fluent/SectionExtensions.cs @@ -6,12 +6,7 @@ namespace QuestPDF.Fluent { public class SectionDescriptor { - private Section Section { get; } - - internal SectionDescriptor(Section section) - { - Section = section; - } + internal Section Section { get; } = new Section(); public IContainer Header() { @@ -36,17 +31,28 @@ namespace QuestPDF.Fluent { handler?.Invoke(Content()); } + + public IContainer Footer() + { + var container = new Container(); + Section.Footer = container; + return container; + } + + public void Footer(Action handler) + { + handler?.Invoke(Footer()); + } } public static class SectionExtensions { public static void Section(this IContainer element, Action handler) { - var section = new Section(); - element.Element(section); - - var descriptor = new SectionDescriptor(section); + var descriptor = new SectionDescriptor(); handler(descriptor); + + element.Component(descriptor.Section); } } } \ No newline at end of file