This commit is contained in:
Marcin Ziąbek 2022-01-27 11:47:24 +01:00
Родитель ac29ed4794
Коммит 97e4572c39
3 изменённых файлов: 114 добавлений и 24 удалений

Просмотреть файл

@ -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<string> 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<MyComponent>(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);
});
});
});
}
}
}

Просмотреть файл

@ -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<T> where T : IComponent
internal class ComponentDescriptor<TComponent> 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<Func<T, ISlot>> selector)
public IContainer Slot(Expression<Func<TComponent, ISlot>> selector)
{
try
AssureThatTheSlotIsNotConfiguredYet(selector);
var slot = new Slot();
Component.SetPropertyValue(selector, slot);
return slot;
}
public void Slot<TArgument>(Expression<Func<TComponent, ISlot<TArgument>>> selector, Action<TArgument, IContainer> handler)
{
AssureThatTheSlotIsNotConfiguredYet(selector);
var slot = new Slot<TArgument>
{
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<TSlot>(Expression<Func<TComponent, TSlot>> 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<T>(this IContainer element, T component, Action<ComponentDescriptor<T>>? handler = null) where T : IComponent
internal static void Component<T>(this IContainer element, T component, Action<ComponentDescriptor<T>>? handler = null) where T : IComponent
{
var descriptor = new ComponentDescriptor<T>(component);
handler?.Invoke(descriptor);
@ -62,15 +74,21 @@ namespace QuestPDF.Fluent
component.Compose(element.Container());
}
static void Component<T>(this IContainer element, Action<ComponentDescriptor<T>>? handler = null) where T : IComponent, new()
internal static void Component<T>(this IContainer element, Action<ComponentDescriptor<T>>? 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<TArgument>(this IContainer element, ISlot<TArgument> slot, TArgument argument)
{
var child = (slot as Slot<TArgument>)?.GetContent(argument) ?? Empty.Instance;
element.Element(child);
}
}
}

Просмотреть файл

@ -1,3 +1,4 @@
using System;
using QuestPDF.Elements;
namespace QuestPDF.Infrastructure
@ -11,7 +12,17 @@ namespace QuestPDF.Infrastructure
{
}
interface ISlot<T>
{
}
class Slot<T> : ISlot<T>
{
public Func<T, IElement> GetContent { get; set; }
}
public interface IComponent
{
void Compose(IContainer container);