diff --git a/QuestPDF.Examples/ComponentExamples.cs b/QuestPDF.Examples/ComponentExamples.cs new file mode 100644 index 0000000..0a3efbe --- /dev/null +++ b/QuestPDF.Examples/ComponentExamples.cs @@ -0,0 +1,61 @@ +using System.Linq; +using NUnit.Framework; +using QuestPDF.Examples.Engine; +using QuestPDF.Fluent; +using QuestPDF.Helpers; +using QuestPDF.Infrastructure; + +namespace QuestPDF.Examples +{ + internal class MyComponent : IComponent + { + public ISlot Header { get; set; } + public ISlot Content { get; set; } + + public void Compose(IContainer container) + { + container + .Column(column => + { + column.Item().Slot(Header); + + foreach (var i in Enumerable.Range(1, 10)) + column.Item().Slot(Content, i.ToString()); + }); + } + } + + public class ComponentExamples + { + [Test] + public void ComplexLayout() + { + RenderingTest + .Create() + .PageSize(PageSizes.A4) + .ProducePdf() + .ShowResults() + .Render(content => + { + content + .Padding(10) + .Border(1) + .BorderColor(Colors.Grey.Medium) + .Component(component => + { + component + .Slot(x => x.Header) + .Text("This is my text"); + + component.Slot(x => x.Content, (input, container) => + { + container + .Background(Placeholders.BackgroundColor()) + .Padding(5) + .Text(input); + }); + }); + }); + } + } +} \ No newline at end of file diff --git a/QuestPDF/Fluent/ComponentExtentions.cs b/QuestPDF/Fluent/ComponentExtentions.cs index cb68962..4a4a1d9 100644 --- a/QuestPDF/Fluent/ComponentExtentions.cs +++ b/QuestPDF/Fluent/ComponentExtentions.cs @@ -1,41 +1,53 @@ using System; using System.Linq.Expressions; using QuestPDF.Drawing.Exceptions; +using QuestPDF.Elements; using QuestPDF.Helpers; using QuestPDF.Infrastructure; namespace QuestPDF.Fluent { - class ComponentDescriptor where T : IComponent + internal class ComponentDescriptor where TComponent : IComponent { - public T Component { get; } + public TComponent Component { get; } - public ComponentDescriptor(T component) + public ComponentDescriptor(TComponent component) { Component = component; } - public IContainer Slot(Expression> selector) + public IContainer Slot(Expression> selector) { - try + AssureThatTheSlotIsNotConfiguredYet(selector); + + var slot = new Slot(); + Component.SetPropertyValue(selector, slot); + return slot; + } + + public void Slot(Expression>> selector, Action handler) + { + AssureThatTheSlotIsNotConfiguredYet(selector); + + var slot = new Slot { - var existingValue = Component.GetPropertyValue(selector); + GetContent = argument => + { + var container = new Container(); + handler(argument, container); + return container; + } + }; + + Component.SetPropertyValue(selector, slot); + } - if (existingValue != null) - throw new DocumentComposeException($"The slot {selector.GetPropertyName()} of the component {(typeof(T).Name)} was already used."); + private void AssureThatTheSlotIsNotConfiguredYet(Expression> selector) where TSlot : class + { + var existingValue = Component.GetPropertyValue(selector); - var slot = new Slot(); - Component.SetPropertyValue(selector, slot); - return slot; - } - catch (DocumentComposeException) - { - throw; - } - catch - { - throw new DocumentComposeException("Every slot in a component should be a public property with getter and setter."); - } + if (existingValue != null) + throw new DocumentComposeException($"The slot {selector.GetPropertyName()} of the component {(typeof(TComponent).Name)} was already used."); } } @@ -51,7 +63,7 @@ namespace QuestPDF.Fluent element.Component(new T(), null); } - static void Component(this IContainer element, T component, Action>? handler = null) where T : IComponent + internal static void Component(this IContainer element, T component, Action>? handler = null) where T : IComponent { var descriptor = new ComponentDescriptor(component); handler?.Invoke(descriptor); @@ -62,15 +74,21 @@ namespace QuestPDF.Fluent component.Compose(element.Container()); } - static void Component(this IContainer element, Action>? handler = null) where T : IComponent, new() + internal static void Component(this IContainer element, Action>? handler = null) where T : IComponent, new() { element.Component(new T(), handler); } - static void Slot(this IContainer element, ISlot slot) + internal static void Slot(this IContainer element, ISlot slot) { var child = (slot as Slot)?.Child; element.Element(child); } + + internal static void Slot(this IContainer element, ISlot slot, TArgument argument) + { + var child = (slot as Slot)?.GetContent(argument) ?? Empty.Instance; + element.Element(child); + } } } \ No newline at end of file diff --git a/QuestPDF/Infrastructure/IComponent.cs b/QuestPDF/Infrastructure/IComponent.cs index dc03736..f2352f5 100644 --- a/QuestPDF/Infrastructure/IComponent.cs +++ b/QuestPDF/Infrastructure/IComponent.cs @@ -1,3 +1,4 @@ +using System; using QuestPDF.Elements; namespace QuestPDF.Infrastructure @@ -11,7 +12,17 @@ namespace QuestPDF.Infrastructure { } - + + interface ISlot + { + + } + + class Slot : ISlot + { + public Func GetContent { get; set; } + } + public interface IComponent { void Compose(IContainer container);