Compare commits
1 Commits
rtl
...
component-slots
| Author | SHA1 | Date | |
|---|---|---|---|
| 97e4572c39 |
@@ -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;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using QuestPDF.Drawing.Exceptions;
|
using QuestPDF.Drawing.Exceptions;
|
||||||
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Helpers;
|
using QuestPDF.Helpers;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
namespace QuestPDF.Fluent
|
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;
|
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)
|
private void AssureThatTheSlotIsNotConfiguredYet<TSlot>(Expression<Func<TComponent, TSlot>> selector) where TSlot : class
|
||||||
throw new DocumentComposeException($"The slot {selector.GetPropertyName()} of the component {(typeof(T).Name)} was already used.");
|
{
|
||||||
|
var existingValue = Component.GetPropertyValue(selector);
|
||||||
|
|
||||||
var slot = new Slot();
|
if (existingValue != null)
|
||||||
Component.SetPropertyValue(selector, slot);
|
throw new DocumentComposeException($"The slot {selector.GetPropertyName()} of the component {(typeof(TComponent).Name)} was already used.");
|
||||||
return slot;
|
|
||||||
}
|
|
||||||
catch (DocumentComposeException)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
throw new DocumentComposeException("Every slot in a component should be a public property with getter and setter.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +63,7 @@ namespace QuestPDF.Fluent
|
|||||||
element.Component(new T(), null);
|
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);
|
var descriptor = new ComponentDescriptor<T>(component);
|
||||||
handler?.Invoke(descriptor);
|
handler?.Invoke(descriptor);
|
||||||
@@ -62,15 +74,21 @@ namespace QuestPDF.Fluent
|
|||||||
component.Compose(element.Container());
|
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);
|
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;
|
var child = (slot as Slot)?.Child;
|
||||||
element.Element(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;
|
using QuestPDF.Elements;
|
||||||
|
|
||||||
namespace QuestPDF.Infrastructure
|
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
|
public interface IComponent
|
||||||
{
|
{
|
||||||
void Compose(IContainer container);
|
void Compose(IContainer container);
|
||||||
|
|||||||
Reference in New Issue
Block a user