Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c80c59996 | |||
| 08a37666fe | |||
| c2fb68562d | |||
| 683ab362d8 | |||
| 04af33fc31 | |||
| 7f94ae589a | |||
| adfce6204e | |||
| 6d3c8d0708 | |||
| 3b8c300126 | |||
| 239a042615 | |||
| 49fb6dadb3 | |||
| c79a4a0c08 | |||
| 31191efd88 | |||
| 20fe49dd01 | |||
| 7cdc1fcee2 | |||
| 14f11232be | |||
| c05c5e1597 | |||
| 07f1eb99b9 | |||
| 44d7538578 | |||
| b894262f7e | |||
| 4423774648 | |||
| 5d4f1f530a | |||
| 3ba8185871 | |||
| b6e0bd505c | |||
| 78e5cbd098 | |||
| f792f6c749 | |||
| 0d86039c0c | |||
| 779245b260 | |||
| 1698212669 | |||
| 388adc5ad1 | |||
| 81a9599b99 | |||
| 48f41db98b | |||
| 3dd8513e42 | |||
| c3d805e5e5 | |||
| f77d8baa63 | |||
| 950d971119 | |||
| e4203838cb | |||
| 25b690fcca | |||
| 4e3ba1d878 | |||
| 3f0b500b1b | |||
| fb3aec4bf8 | |||
| 8c2250ecde | |||
| bb2850b2d8 | |||
| 842b856f7a | |||
| 733dbc8746 | |||
| 0b7b05d36c | |||
| a83ebe2fed | |||
| 6f0c6513da | |||
| 500cea1fbf | |||
| 3369da42ed | |||
| c5cb588857 | |||
| 08126b2fa4 | |||
| 5e9ff7ec1e | |||
| 9c05c182b8 | |||
| dee97b22e4 | |||
| 1d1d969b5a | |||
| 190b1e7dee | |||
| 98be1abe74 | |||
| 6b6d2d7fa3 |
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Please provide an example, minimalistic code that shows the problem.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,76 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at marcin@ziabek.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Examples
|
||||
{
|
||||
public class BarCode
|
||||
{
|
||||
[Test]
|
||||
public void Example()
|
||||
{
|
||||
FontManager.RegisterFontType("LibreBarcode39", File.OpenRead("LibreBarcode39-Regular.ttf"));
|
||||
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(400, 100)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background(Colors.White)
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
.Text("*QuestPDF*", TextStyle.Default.FontType("LibreBarcode39").Size(64));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Examples
|
||||
{
|
||||
public class ContinuousPageDocument : IDocument
|
||||
{
|
||||
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
|
||||
|
||||
public void Compose(IDocumentContainer container)
|
||||
{
|
||||
container.Page(page =>
|
||||
{
|
||||
page.Margin(20);
|
||||
page.ContinuousSize(150);
|
||||
|
||||
page.Header().Text("Header");
|
||||
|
||||
page.Content().PaddingVertical(10).Border(1).Padding(10).Stack(stack =>
|
||||
{
|
||||
foreach (var index in Enumerable.Range(1, 100))
|
||||
stack.Item().Text($"Line {index}", TextStyle.Default.Color(Placeholders.Color()));
|
||||
});
|
||||
|
||||
page.Footer().Text("Footer");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class ContinuousPageExamples
|
||||
{
|
||||
[Test]
|
||||
public void ContinuousPage()
|
||||
{
|
||||
var path = "example.pdf";
|
||||
new ContinuousPageDocument().GeneratePdf(path);
|
||||
Process.Start("explorer", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,138 +1,837 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace QuestPDF.Examples
|
||||
{
|
||||
public class ElementExamples : ExampleTestBase
|
||||
[TestFixture]
|
||||
public class ElementExamples
|
||||
{
|
||||
//[ShowResult]
|
||||
[ImageSize(200, 150)]
|
||||
public void Placeholder(IContainer container)
|
||||
[Test]
|
||||
public void Placeholder()
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Placeholder();
|
||||
}
|
||||
|
||||
//[ShowResult]
|
||||
[ImageSize(300, 300)]
|
||||
public void Section(IContainer container)
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Section(section =>
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
section
|
||||
.Header()
|
||||
.Background("#888")
|
||||
.Padding(10)
|
||||
.Text("Notes", TextStyle.Default.Size(16).Color("#FFF"));
|
||||
|
||||
section
|
||||
.Content()
|
||||
.Background("#DDD")
|
||||
.Padding(10)
|
||||
.ExtendVertical()
|
||||
.Text(TextPlaceholder.LoremIpsum());
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Placeholder();
|
||||
});
|
||||
}
|
||||
|
||||
//[ShowResult]
|
||||
[ImageSize(298, 421)]
|
||||
public void Page(IContainer container)
|
||||
[Test]
|
||||
public void Decoration()
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(15)
|
||||
.Page(page =>
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
page.Header()
|
||||
.Height(60)
|
||||
.Background("#BBB")
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
.Text("Header");
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Decoration(decoration =>
|
||||
{
|
||||
decoration
|
||||
.Header()
|
||||
.Background(Colors.Grey.Medium)
|
||||
.Padding(10)
|
||||
.Text("Notes", TextStyle.Default.Size(16).Color("#FFF"));
|
||||
|
||||
page.Content()
|
||||
.Background("#DDD")
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
.Text("Content");
|
||||
decoration
|
||||
.Content()
|
||||
.Background(Colors.Grey.Lighten3)
|
||||
.Padding(10)
|
||||
.ExtendVertical()
|
||||
.Text(Helpers.Placeholders.LoremIpsum());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Row()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(740, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(20)
|
||||
.Stack(stack =>
|
||||
{
|
||||
stack.Item()
|
||||
.PaddingBottom(10)
|
||||
.AlignCenter()
|
||||
.Text("This Row element is 700pt wide");
|
||||
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.ConstantColumn(100)
|
||||
.Background(Colors.Grey.Lighten1)
|
||||
.Padding(10)
|
||||
.ExtendVertical()
|
||||
.Text("This column is 100 pt wide");
|
||||
|
||||
row.RelativeColumn()
|
||||
.Background(Colors.Grey.Lighten2)
|
||||
.Padding(10)
|
||||
.Text("This column takes 1/3 of the available space (200pt)");
|
||||
|
||||
row.RelativeColumn(2)
|
||||
.Background(Colors.Grey.Lighten3)
|
||||
.Padding(10)
|
||||
.Text("This column takes 2/3 of the available space (400pt)");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RowSpacing()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(740, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(20)
|
||||
.Row(row =>
|
||||
{
|
||||
row.Spacing(20);
|
||||
row.RelativeColumn(2).Border(1).Background(Colors.Grey.Lighten1);
|
||||
row.RelativeColumn(3).Border(1).Background(Colors.Grey.Lighten2);
|
||||
row.RelativeColumn(4).Border(1).Background(Colors.Grey.Lighten3);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Stack()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 360)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(15)
|
||||
.Stack(stack =>
|
||||
{
|
||||
stack.Spacing(15);
|
||||
|
||||
stack.Item().Background(Colors.Grey.Medium).Height(50);
|
||||
stack.Item().Background(Colors.Grey.Lighten1).Height(100);
|
||||
stack.Item().Background(Colors.Grey.Lighten2).Height(150);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Debug()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(210, 210)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Debug("Grid example", Colors.Blue.Medium)
|
||||
.Grid(grid =>
|
||||
{
|
||||
grid.Columns(3);
|
||||
grid.Spacing(5);
|
||||
|
||||
foreach (var _ in Enumerable.Range(0, 8))
|
||||
grid.Item().Height(50).Placeholder();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ElementEnd()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
var text = "";
|
||||
|
||||
container
|
||||
.Padding(10)
|
||||
.Element(x =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
x.Height(10).Width(50).Background("#DDD");
|
||||
else
|
||||
x.Text(text);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GridExample()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(400, 230)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
var textStyle = TextStyle.Default.Size(14);
|
||||
|
||||
container
|
||||
.Padding(15)
|
||||
.AlignRight()
|
||||
.Grid(grid =>
|
||||
{
|
||||
grid.VerticalSpacing(10);
|
||||
grid.HorizontalSpacing(10);
|
||||
grid.AlignCenter();
|
||||
grid.Columns(10); // 12 by default
|
||||
|
||||
grid.Item(6).Background(Colors.Blue.Lighten1).Height(50);
|
||||
grid.Item(4).Background(Colors.Blue.Lighten3).Height(50);
|
||||
|
||||
grid.Item(2).Background(Colors.Teal.Lighten1).Height(70);
|
||||
grid.Item(3).Background(Colors.Teal.Lighten2).Height(70);
|
||||
grid.Item(5).Background(Colors.Teal.Lighten3).Height(70);
|
||||
|
||||
grid.Item(2).Background(Colors.Green.Lighten1).Height(50);
|
||||
grid.Item(2).Background(Colors.Green.Lighten2).Height(50);
|
||||
grid.Item(2).Background(Colors.Green.Lighten3).Height(50);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Canvas()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Canvas((canvas, size) =>
|
||||
{
|
||||
using var paint = new SKPaint
|
||||
{
|
||||
Color = SKColors.Red,
|
||||
StrokeWidth = 10,
|
||||
IsStroke = true
|
||||
};
|
||||
|
||||
// move origin to the center of the available space
|
||||
canvas.Translate(size.Width / 2, size.Height / 2);
|
||||
|
||||
// draw a circle
|
||||
canvas.DrawCircle(0, 0, 50, paint);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LayersExample()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(400, 250)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Layers(layers =>
|
||||
{
|
||||
// layer below main content
|
||||
layers
|
||||
.Layer()
|
||||
.Height(100)
|
||||
.Width(100)
|
||||
.Background(Colors.Grey.Lighten3);
|
||||
|
||||
layers
|
||||
.PrimaryLayer()
|
||||
.Padding(25)
|
||||
.Stack(stack =>
|
||||
{
|
||||
stack.Spacing(5);
|
||||
|
||||
foreach (var _ in Enumerable.Range(0, 7))
|
||||
stack.Item().Text(Placeholders.Sentence());
|
||||
});
|
||||
|
||||
// layer above the main content
|
||||
layers
|
||||
.Layer()
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
.Text("Watermark", TextStyle.Default.Size(48).Bold().Color(Colors.Green.Lighten3));
|
||||
|
||||
layers
|
||||
.Layer()
|
||||
.AlignBottom()
|
||||
.PageNumber("Page {pdf:currentPage}", TextStyle.Default.Size(16).Color(Colors.Green.Medium));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public void EnsureSpace()
|
||||
// {
|
||||
// RenderingTest
|
||||
// .Create()
|
||||
// .PageSize(300, 400)
|
||||
// .Render(container =>
|
||||
// {
|
||||
// container
|
||||
// .Padding(50)
|
||||
// .Page(page =>
|
||||
// {
|
||||
// page.Header().PageNumber("Page {pdf:currentPage}");
|
||||
//
|
||||
// page.Content().Height(300).Stack(content =>
|
||||
// {
|
||||
// content.Item().Height(200).Background(Colors.Grey.Lighten2);
|
||||
//
|
||||
// content.Item().EnsureSpace(100).Stack(stack =>
|
||||
// {
|
||||
// stack.Spacing(10);
|
||||
//
|
||||
// foreach (var _ in Enumerable.Range(0, 4))
|
||||
// stack.Item().Height(50).Background(Colors.Green.Lighten1);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void RandomColorMatrix()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Grid(grid =>
|
||||
{
|
||||
grid.Columns(5);
|
||||
|
||||
Enumerable
|
||||
.Range(0, 25)
|
||||
.Select(x => Placeholders.BackgroundColor())
|
||||
.ToList()
|
||||
.ForEach(x => grid.Item().Height(50).Background(x));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefinedColors()
|
||||
{
|
||||
var colors = new[]
|
||||
{
|
||||
Colors.Green.Darken4,
|
||||
Colors.Green.Darken3,
|
||||
Colors.Green.Darken2,
|
||||
Colors.Green.Darken1,
|
||||
|
||||
Colors.Green.Medium,
|
||||
|
||||
Colors.Green.Lighten1,
|
||||
Colors.Green.Lighten2,
|
||||
Colors.Green.Lighten3,
|
||||
Colors.Green.Lighten4,
|
||||
Colors.Green.Lighten5,
|
||||
|
||||
Colors.Green.Accent1,
|
||||
Colors.Green.Accent2,
|
||||
Colors.Green.Accent3,
|
||||
Colors.Green.Accent4,
|
||||
};
|
||||
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(450, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Height(100)
|
||||
.Row(row =>
|
||||
{
|
||||
foreach (var color in colors)
|
||||
row.RelativeColumn().Background(color);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefinedFonts()
|
||||
{
|
||||
var fonts = new[]
|
||||
{
|
||||
Fonts.Calibri,
|
||||
Fonts.Candara,
|
||||
Fonts.Arial,
|
||||
Fonts.TimesNewRoman,
|
||||
Fonts.Consolas,
|
||||
Fonts.Tahoma,
|
||||
Fonts.Impact,
|
||||
Fonts.Trebuchet,
|
||||
Fonts.ComicSans
|
||||
};
|
||||
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 175)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Grid(grid =>
|
||||
{
|
||||
grid.Columns(3);
|
||||
|
||||
foreach (var font in fonts)
|
||||
{
|
||||
grid.Item()
|
||||
.Border(1)
|
||||
.BorderColor(Colors.Grey.Medium)
|
||||
.Padding(10)
|
||||
.Text(font, TextStyle.Default.FontType(font).Size(16));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Layers()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Layers(layers =>
|
||||
{
|
||||
layers.Layer().Text("Something else");
|
||||
|
||||
layers.PrimaryLayer().Stack(stack =>
|
||||
{
|
||||
stack.Item().PaddingTop(20).Text("Text 1");
|
||||
stack.Item().PaddingTop(40).Text("Text 2");
|
||||
});
|
||||
|
||||
layers.Layer().Canvas((canvas, size) =>
|
||||
{
|
||||
using var paint = new SKPaint
|
||||
{
|
||||
Color = SKColors.Red,
|
||||
StrokeWidth = 5
|
||||
};
|
||||
|
||||
canvas.Translate(size.Width / 2, size.Height / 2);
|
||||
canvas.DrawCircle(0, 0, 50, paint);
|
||||
});
|
||||
|
||||
layers.Layer().Background("#8F00").Extend();
|
||||
layers.Layer().PaddingTop(40).Text("It works!", TextStyle.Default.Size(24));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Box()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(15)
|
||||
.Border(4)
|
||||
.BorderColor(Colors.Blue.Medium)
|
||||
//.Box()
|
||||
.Background(Colors.Grey.Lighten2)
|
||||
.Padding(15)
|
||||
.Text("Test of the \n box element", TextStyle.Default.Size(20));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Scale()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(400, 250)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Stack(stack =>
|
||||
{
|
||||
var scales = new[] { 0.75f, 1f, 1.25f, 1.5f };
|
||||
|
||||
foreach (var scale in scales)
|
||||
{
|
||||
stack
|
||||
.Item()
|
||||
.Border(1)
|
||||
.Scale(scale)
|
||||
.Padding(10)
|
||||
.Text($"Content with {scale} scale.", TextStyle.Default.Size(20));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Translate()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Box()
|
||||
|
||||
.Padding(25)
|
||||
|
||||
.Background(Colors.Green.Lighten3)
|
||||
|
||||
.TranslateX(15)
|
||||
.TranslateY(15)
|
||||
|
||||
.Border(2)
|
||||
.BorderColor(Colors.Green.Darken1)
|
||||
|
||||
.Padding(50)
|
||||
.Text("Moved text", TextStyle.Default.Size(25));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConstrainedRotate()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(350, 350)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(20)
|
||||
.Grid(grid =>
|
||||
{
|
||||
grid.Columns(2);
|
||||
grid.Spacing(10);
|
||||
|
||||
foreach (var turns in Enumerable.Range(0, 4))
|
||||
{
|
||||
grid.Item()
|
||||
.Width(150)
|
||||
.Height(150)
|
||||
.Background(Colors.Grey.Lighten2)
|
||||
.Padding(10)
|
||||
.Element(element =>
|
||||
{
|
||||
foreach (var x in Enumerable.Range(0, turns))
|
||||
element = element.RotateRight();
|
||||
|
||||
return element;
|
||||
})
|
||||
.Box()
|
||||
.Background(Colors.White)
|
||||
.Padding(10)
|
||||
.Text($"Rotated {turns * 90}°", TextStyle.Default.Size(16));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FreeRotate()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Background(Colors.Grey.Lighten2)
|
||||
|
||||
page.Footer()
|
||||
.Height(30)
|
||||
.Background("#BBB")
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
.Text("Footer");
|
||||
|
||||
|
||||
.Background(Colors.White)
|
||||
|
||||
.Rotate(30)
|
||||
|
||||
.Width(100)
|
||||
.Height(100)
|
||||
.Background(Colors.Blue.Medium);
|
||||
});
|
||||
}
|
||||
|
||||
//[ShowResult]
|
||||
[ImageSize(740, 200)]
|
||||
public void Row(IContainer container)
|
||||
[Test]
|
||||
public void FreeRotateCenter()
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(20)
|
||||
.Stack(stack =>
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
stack.Element()
|
||||
.PaddingBottom(10)
|
||||
container
|
||||
.Padding(25)
|
||||
.Background(Colors.Grey.Lighten2)
|
||||
|
||||
.AlignCenter()
|
||||
.Text("This Row element is 700pt wide");
|
||||
.AlignMiddle()
|
||||
|
||||
.Background(Colors.White)
|
||||
|
||||
.TranslateX(50)
|
||||
.TranslateY(50)
|
||||
|
||||
.Rotate(30)
|
||||
|
||||
stack.Element().Row(row =>
|
||||
{
|
||||
row.ConstantColumn(100)
|
||||
.Background("#DDD")
|
||||
.Padding(10)
|
||||
.ExtendVertical()
|
||||
.Text("This column is 100 pt wide");
|
||||
.TranslateX(-50)
|
||||
.TranslateY(-50)
|
||||
|
||||
.Width(100)
|
||||
.Height(100)
|
||||
.Background(Colors.Blue.Medium);
|
||||
});
|
||||
}
|
||||
|
||||
row.RelativeColumn()
|
||||
.Background("#BBB")
|
||||
.Padding(10)
|
||||
.Text("This column takes 1/3 of the available space (200pt)");
|
||||
[Test]
|
||||
public void Flip()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(350, 350)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(20)
|
||||
.Grid(grid =>
|
||||
{
|
||||
grid.Columns(2);
|
||||
grid.Spacing(10);
|
||||
|
||||
foreach (var turns in Enumerable.Range(0, 4))
|
||||
{
|
||||
grid.Item()
|
||||
.Width(150)
|
||||
.Height(150)
|
||||
.Background(Colors.Grey.Lighten3)
|
||||
.Padding(10)
|
||||
.Element(element =>
|
||||
{
|
||||
if (turns == 1 || turns == 2)
|
||||
element = element.FlipHorizontal();
|
||||
|
||||
row.RelativeColumn(2)
|
||||
.Background("#DDD")
|
||||
.Padding(10)
|
||||
.Text("This column takes 2/3 of the available space (400pt)");
|
||||
});
|
||||
if (turns == 2 || turns == 3)
|
||||
element = element.FlipVertical();
|
||||
|
||||
return element;
|
||||
})
|
||||
.Box()
|
||||
.Background(Colors.White)
|
||||
.Padding(10)
|
||||
.Text($"Flipped {turns}", TextStyle.Default.Size(16));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//[ShowResult]
|
||||
[ImageSize(500, 350)]
|
||||
public void Column(IContainer container)
|
||||
[Test]
|
||||
public void RotateInTable()
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(15)
|
||||
.Stack(column =>
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
column.Spacing(10);
|
||||
|
||||
column
|
||||
.Element()
|
||||
.Background("#999")
|
||||
.Height(50);
|
||||
|
||||
column
|
||||
.Element()
|
||||
.Background("#BBB")
|
||||
.Height(100);
|
||||
|
||||
column
|
||||
.Element()
|
||||
.Background("#DDD")
|
||||
.Height(150);
|
||||
container
|
||||
.Padding(10)
|
||||
.Border(2)
|
||||
.Row(row =>
|
||||
{
|
||||
row.ConstantColumn(25)
|
||||
.Border(1)
|
||||
.RotateLeft()
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
.Text("Sample text");
|
||||
|
||||
row.RelativeColumn().Border(1).Padding(5).Text(Placeholders.Paragraph());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Unconstrained()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(400, 350)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.PaddingLeft(75)
|
||||
.Stack(stack =>
|
||||
{
|
||||
stack.Item().Width(300).Height(150).Background(Colors.Blue.Lighten4);
|
||||
|
||||
stack
|
||||
.Item()
|
||||
|
||||
// creates an infinite space for its child
|
||||
.Unconstrained()
|
||||
|
||||
// moves the child up and left
|
||||
.TranslateX(-50)
|
||||
.TranslateY(-50)
|
||||
|
||||
// limits the space for the child
|
||||
.Width(100)
|
||||
.Height(100)
|
||||
|
||||
.Background(Colors.Blue.Darken1);
|
||||
|
||||
stack.Item().Width(300).Height(150).Background(Colors.Blue.Lighten3);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ComplexLayout()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 225)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Stack(stack =>
|
||||
{
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeColumn().LabelCell("Label 1");
|
||||
|
||||
row.RelativeColumn(3).Grid(grid =>
|
||||
{
|
||||
grid.Columns(3);
|
||||
|
||||
grid.Item(2).LabelCell("Label 2");
|
||||
grid.Item().LabelCell("Label 3");
|
||||
|
||||
grid.Item(2).ValueCell().Text("Value 2");
|
||||
grid.Item().ValueCell().Text("Value 3");
|
||||
});
|
||||
});
|
||||
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeColumn().ValueCell().Text("Value 1");
|
||||
|
||||
row.RelativeColumn(3).Grid(grid =>
|
||||
{
|
||||
grid.Columns(3);
|
||||
|
||||
grid.Item().LabelCell("Label 4");
|
||||
grid.Item(2).LabelCell("Label 5");
|
||||
|
||||
grid.Item().ValueCell().Text("Value 4");
|
||||
grid.Item(2).ValueCell().Text("Value 5");
|
||||
});
|
||||
});
|
||||
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeColumn().LabelCell("Label 6");
|
||||
row.RelativeColumn().ValueCell().Text("Value 6");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DomainSpecificLanguage()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(600, 310)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Grid(grid =>
|
||||
{
|
||||
grid.Columns(10);
|
||||
|
||||
for(var i=1; i<=4; i++)
|
||||
{
|
||||
grid.Item(2).LabelCell(Placeholders.Label());
|
||||
grid.Item(3).ValueCell().Image(Placeholders.Image(200, 150));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Infrastructure;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
[TestFixture]
|
||||
public class ExampleTestBase
|
||||
{
|
||||
private readonly Size DefaultImageSize = new Size(400, 300);
|
||||
private const string ResultPath = "Result";
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
if (Directory.Exists(ResultPath))
|
||||
Directory.Delete(ResultPath, true);
|
||||
|
||||
Directory.CreateDirectory(ResultPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RunTest()
|
||||
{
|
||||
GetType()
|
||||
.GetMethods()
|
||||
.Where(IsExampleMethod)
|
||||
.ToList()
|
||||
.ForEach(HandleExample);
|
||||
}
|
||||
|
||||
private bool IsExampleMethod(MethodInfo method)
|
||||
{
|
||||
var parameters = method.GetParameters();
|
||||
return parameters.Length == 1 && parameters.First().ParameterType == typeof(IContainer);
|
||||
}
|
||||
|
||||
private T GetAttribute<T>(MethodInfo methodInfo) where T : Attribute
|
||||
{
|
||||
return methodInfo.GetCustomAttributes().FirstOrDefault(y => y is T) as T;
|
||||
}
|
||||
|
||||
private void HandleExample(MethodInfo methodInfo)
|
||||
{
|
||||
var size = GetAttribute<ImageSizeAttribute>(methodInfo)?.Size ?? DefaultImageSize;
|
||||
var fileName = GetAttribute<FileNameAttribute>(methodInfo)?.FileName ?? methodInfo.Name;
|
||||
var showResult = GetAttribute<ShowResultAttribute>(methodInfo) != null;
|
||||
var shouldIgnore = GetAttribute<IgnoreAttribute>(methodInfo) != null;
|
||||
|
||||
if (shouldIgnore)
|
||||
return;
|
||||
|
||||
var container = new Container();
|
||||
methodInfo.Invoke(this, new object[] {container});
|
||||
|
||||
Func<int, string> fileNameSchema = i => $"{fileName.ToLower()}-${i}.png";
|
||||
|
||||
var document = new SimpleDocument(container, size);
|
||||
document.GenerateImages(fileNameSchema);
|
||||
|
||||
if (showResult)
|
||||
Process.Start("explorer", fileNameSchema(0));
|
||||
}
|
||||
|
||||
private byte[] RenderPage(Element element, Size size)
|
||||
{
|
||||
// scale the result so it is more readable
|
||||
const float scalingFactor = 2;
|
||||
|
||||
var imageInfo = new SKImageInfo((int)(size.Width * scalingFactor), (int)(size.Height * scalingFactor));
|
||||
using var surface = SKSurface.Create(imageInfo);
|
||||
surface.Canvas.Scale(scalingFactor);
|
||||
|
||||
var canvas = new Canvas(surface.Canvas);
|
||||
element?.Draw(canvas, size);
|
||||
|
||||
surface.Canvas.Save();
|
||||
return surface.Snapshot().Encode(SKEncodedImageFormat.Png, 100).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
public class FileNameAttribute : Attribute
|
||||
{
|
||||
public string FileName { get; }
|
||||
|
||||
public FileNameAttribute(string fileName)
|
||||
{
|
||||
FileName = fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
public class IgnoreAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
public class ImageSizeAttribute : Attribute
|
||||
{
|
||||
private int Width { get; }
|
||||
private int Height { get; }
|
||||
|
||||
public Size Size => new Size(Width, Height);
|
||||
|
||||
public ImageSizeAttribute(int width, int height)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
public class RenderingTest
|
||||
{
|
||||
private string FileNamePrefix = "test";
|
||||
private Size Size { get; set; }
|
||||
|
||||
private RenderingTest()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static RenderingTest Create()
|
||||
{
|
||||
return new RenderingTest();
|
||||
}
|
||||
|
||||
public RenderingTest FileName([CallerMemberName] string fileName = "test")
|
||||
{
|
||||
FileNamePrefix = fileName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RenderingTest PageSize(int width, int height)
|
||||
{
|
||||
Size = new Size(width, height);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Render(Action<IContainer> content)
|
||||
{
|
||||
var container = new Container();
|
||||
content(container);
|
||||
|
||||
Func<int, string> fileNameSchema = i => $"{FileNamePrefix}-${i}.png";
|
||||
|
||||
var document = new SimpleDocument(container, Size);
|
||||
document.GenerateImages(fileNameSchema);
|
||||
|
||||
Process.Start("explorer", fileNameSchema(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
public class ShowResultAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
@@ -7,6 +8,8 @@ namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
public class SimpleDocument : IDocument
|
||||
{
|
||||
public const int ImageScalingFactor = 2;
|
||||
|
||||
private IContainer Container { get; }
|
||||
private Size Size { get; }
|
||||
|
||||
@@ -20,14 +23,18 @@ namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
return new DocumentMetadata()
|
||||
{
|
||||
RasterDpi = PageSizes.PointsPerInch * 2,
|
||||
Size = Size
|
||||
RasterDpi = PageSizes.PointsPerInch * ImageScalingFactor,
|
||||
DocumentLayoutExceptionThreshold = 10
|
||||
};
|
||||
}
|
||||
|
||||
public void Compose(IContainer container)
|
||||
|
||||
public void Compose(IDocumentContainer container)
|
||||
{
|
||||
container.Element(Container.Child);
|
||||
container.Page(page =>
|
||||
{
|
||||
page.Size(new PageSize(Size.Width, Size.Height));
|
||||
page.Content().Container().Background(Colors.White).Element(Container as Container);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
@@ -12,33 +12,39 @@ namespace QuestPDF.Examples
|
||||
{
|
||||
return container
|
||||
.Border(1)
|
||||
.Background(dark ? "#EEE" : "#FFF")
|
||||
.Background(dark ? Colors.Grey.Lighten2 : Colors.White)
|
||||
.Padding(10);
|
||||
}
|
||||
|
||||
public static IContainer LabelCell(this IContainer container) => container.Cell(true);
|
||||
public static void LabelCell(this IContainer container, string text) => container.Cell(true).Text(text, TextStyle.Default.Medium());
|
||||
public static IContainer ValueCell(this IContainer container) => container.Cell(false);
|
||||
}
|
||||
|
||||
public class FrameExample: ExampleTestBase
|
||||
public class FrameExample
|
||||
{
|
||||
[ImageSize(550, 400)]
|
||||
[ShowResult]
|
||||
[Test]
|
||||
public void Frame(IContainer container)
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Stack(stack =>
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(550, 400)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
for(var i=1; i<=4; i++)
|
||||
{
|
||||
stack.Element().Row(row =>
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Stack(stack =>
|
||||
{
|
||||
row.RelativeColumn(2).LabelCell().Text(TextPlaceholder.Label());
|
||||
row.RelativeColumn(3).ValueCell().Text(TextPlaceholder.Paragraph());
|
||||
for(var i=1; i<=4; i++)
|
||||
{
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeColumn(2).LabelCell(Placeholders.Label());
|
||||
row.RelativeColumn(3).ValueCell().Text(Placeholders.Paragraph());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Net;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Infrastructure;
|
||||
@@ -27,27 +28,33 @@ namespace QuestPDF.Examples
|
||||
}
|
||||
}
|
||||
|
||||
public class LoremPicsumExample : ExampleTestBase
|
||||
public class LoremPicsumExample
|
||||
{
|
||||
[ShowResult]
|
||||
[ImageSize(350, 280)]
|
||||
public void LoremPicsum(IContainer container)
|
||||
[Test]
|
||||
public void LoremPicsum()
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Stack(column =>
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(350, 280)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
column.Spacing(10);
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Stack(column =>
|
||||
{
|
||||
column.Spacing(10);
|
||||
|
||||
column
|
||||
.Element()
|
||||
.Component(new LoremPicsum(true));
|
||||
column
|
||||
.Item()
|
||||
.Component(new LoremPicsum(true));
|
||||
|
||||
column
|
||||
.Element()
|
||||
.AlignRight()
|
||||
.Text("From Lorem Picsum");
|
||||
column
|
||||
.Item()
|
||||
.AlignRight()
|
||||
.Text("From Lorem Picsum");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,132 +1,165 @@
|
||||
using QuestPDF.Examples.Engine;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Examples
|
||||
{
|
||||
public class Examples : ExampleTestBase
|
||||
public class Examples
|
||||
{
|
||||
public void Padding(IContainer container)
|
||||
[Test]
|
||||
public void Padding()
|
||||
{
|
||||
container
|
||||
.Background("#FDD")
|
||||
.Padding(50)
|
||||
|
||||
.Background("#AFA")
|
||||
.PaddingVertical(50)
|
||||
|
||||
.Background("#77F")
|
||||
.PaddingHorizontal(50)
|
||||
|
||||
.Background("#444");
|
||||
}
|
||||
|
||||
public void Border(IContainer container)
|
||||
{
|
||||
container
|
||||
.Background("#EEE")
|
||||
.Padding(25)
|
||||
|
||||
.AlignBottom()
|
||||
.AlignCenter()
|
||||
.BorderBottom(2)
|
||||
.BorderColor("#000")
|
||||
|
||||
.Background("FFF")
|
||||
.Padding(5)
|
||||
.Text("Sample text", TextStyle.Default.FontType("Segoe UI emoji").Alignment(HorizontalAlignment.Center));
|
||||
}
|
||||
|
||||
public void Alignment(IContainer container)
|
||||
{
|
||||
container
|
||||
.Stack(column =>
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
column
|
||||
.Element()
|
||||
.Height(100)
|
||||
.Background("#FFF")
|
||||
|
||||
.AlignLeft()
|
||||
.AlignMiddle()
|
||||
container
|
||||
.Background("#FDD")
|
||||
.Padding(50)
|
||||
|
||||
.Background("#AFA")
|
||||
.PaddingVertical(50)
|
||||
|
||||
.Background("#77F")
|
||||
.PaddingHorizontal(50)
|
||||
|
||||
.Width(50)
|
||||
.Height(50)
|
||||
.Background("#444");
|
||||
|
||||
column
|
||||
.Element()
|
||||
.Height(100)
|
||||
.Background("#DDD")
|
||||
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
|
||||
.Width(50)
|
||||
.Height(50)
|
||||
.Background("#222");
|
||||
|
||||
column
|
||||
.Element()
|
||||
.Height(100)
|
||||
.Background("#BBB")
|
||||
|
||||
.AlignRight()
|
||||
.AlignMiddle()
|
||||
|
||||
.Width(50)
|
||||
.Height(50)
|
||||
.Background("#000");
|
||||
});
|
||||
}
|
||||
|
||||
public void Expand(IContainer container)
|
||||
[Test]
|
||||
public void Border()
|
||||
{
|
||||
container
|
||||
.Stack(column =>
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
column
|
||||
.Element()
|
||||
.Height(150)
|
||||
.Row(row =>
|
||||
container
|
||||
.Background("#EEE")
|
||||
.Padding(25)
|
||||
|
||||
.AlignBottom()
|
||||
.AlignCenter()
|
||||
.BorderBottom(2)
|
||||
.BorderColor("#000")
|
||||
|
||||
.Background("FFF")
|
||||
.Padding(5)
|
||||
.Text("Sample text", TextStyle.Default.FontType("Segoe UI emoji").Alignment(HorizontalAlignment.Center));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Alignment()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Stack(column =>
|
||||
{
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("FFF")
|
||||
column
|
||||
.Item()
|
||||
.Height(100)
|
||||
.Background("#FFF")
|
||||
|
||||
.AlignLeft()
|
||||
.AlignMiddle()
|
||||
|
||||
.Height(50)
|
||||
.Width(50)
|
||||
.Background("444");
|
||||
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("BBB")
|
||||
|
||||
.Height(50)
|
||||
.ExtendHorizontal()
|
||||
.Background("444");
|
||||
});
|
||||
.Background("#444");
|
||||
|
||||
column
|
||||
.Element()
|
||||
.Height(150)
|
||||
.Row(row =>
|
||||
{
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("BBB")
|
||||
column
|
||||
.Item()
|
||||
.Height(100)
|
||||
.Background("#DDD")
|
||||
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
|
||||
.ExtendVertical()
|
||||
.Width(50)
|
||||
.Background("444");
|
||||
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("BBB")
|
||||
.Height(50)
|
||||
.Background("#222");
|
||||
|
||||
column
|
||||
.Item()
|
||||
.Height(100)
|
||||
.Background("#BBB")
|
||||
|
||||
.AlignRight()
|
||||
.AlignMiddle()
|
||||
|
||||
.ExtendVertical()
|
||||
.ExtendHorizontal()
|
||||
.Background("444");
|
||||
.Width(50)
|
||||
.Height(50)
|
||||
.Background("#000");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Expand()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Stack(column =>
|
||||
{
|
||||
column
|
||||
.Item()
|
||||
.Height(150)
|
||||
.Row(row =>
|
||||
{
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("FFF")
|
||||
|
||||
.Height(50)
|
||||
.Width(50)
|
||||
.Background("444");
|
||||
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("BBB")
|
||||
|
||||
.Height(50)
|
||||
.ExtendHorizontal()
|
||||
.Background("444");
|
||||
});
|
||||
|
||||
column
|
||||
.Item()
|
||||
.Height(150)
|
||||
.Row(row =>
|
||||
{
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("BBB")
|
||||
|
||||
.ExtendVertical()
|
||||
.Width(50)
|
||||
.Background("444");
|
||||
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("BBB")
|
||||
|
||||
.ExtendVertical()
|
||||
.ExtendHorizontal()
|
||||
.Background("444");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -13,8 +13,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\QuestPDF.InvoiceSample\QuestPDF.InvoiceSample.csproj" />
|
||||
<ProjectReference Include="..\QuestPDF\QuestPDF.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="LibreBarcode39-Regular.ttf">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.ReportSample.Layouts;
|
||||
|
||||
namespace QuestPDF.ReportSample
|
||||
{
|
||||
@@ -18,9 +17,9 @@ namespace QuestPDF.ReportSample
|
||||
Title = "Sample Report Document",
|
||||
HeaderFields = HeaderFields(),
|
||||
|
||||
LogoData = Helpers.GetImage("logo.png"),
|
||||
Sections = Enumerable.Range(0, 10).Select(x => GenerateSection()).ToList(),
|
||||
Photos = Enumerable.Range(0, 10).Select(x => GetReportPhotos()).ToList()
|
||||
LogoData = Helpers.GetImage("Logo.png"),
|
||||
Sections = Enumerable.Range(0, 50).Select(x => GenerateSection()).ToList(),
|
||||
Photos = Enumerable.Range(0, 30).Select(x => GetReportPhotos()).ToList()
|
||||
};
|
||||
|
||||
List<ReportHeaderField> HeaderFields()
|
||||
@@ -41,6 +40,11 @@ namespace QuestPDF.ReportSample
|
||||
{
|
||||
Label = "Date",
|
||||
Value = DateTime.Now.ToString("g")
|
||||
},
|
||||
new ReportHeaderField()
|
||||
{
|
||||
Label = "Status",
|
||||
Value = "Completed, found 2 issues"
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -48,12 +52,12 @@ namespace QuestPDF.ReportSample
|
||||
ReportSection GenerateSection()
|
||||
{
|
||||
var sectionLength = Helpers.Random.NextDouble() > 0.75
|
||||
? Helpers.Random.Next(10, 20)
|
||||
: Helpers.Random.Next(3, 11);
|
||||
? Helpers.Random.Next(20, 40)
|
||||
: Helpers.Random.Next(5, 10);
|
||||
|
||||
return new ReportSection
|
||||
{
|
||||
Title = TextPlaceholder.Label(),
|
||||
Title = Placeholders.Label(),
|
||||
Parts = Enumerable.Range(0, sectionLength).Select(x => GetRandomElement()).ToList()
|
||||
};
|
||||
}
|
||||
@@ -62,10 +66,10 @@ namespace QuestPDF.ReportSample
|
||||
{
|
||||
var random = Helpers.Random.NextDouble();
|
||||
|
||||
if (random < 0.8f)
|
||||
if (random < 0.9f)
|
||||
return GetTextElement();
|
||||
|
||||
if (random < 0.9f)
|
||||
if (random < 0.95f)
|
||||
return GetMapElement();
|
||||
|
||||
return GetPhotosElement();
|
||||
@@ -75,19 +79,17 @@ namespace QuestPDF.ReportSample
|
||||
{
|
||||
return new ReportSectionText
|
||||
{
|
||||
Label = TextPlaceholder.Label(),
|
||||
Text = TextPlaceholder.Paragraph()
|
||||
Label = Placeholders.Label(),
|
||||
Text = Placeholders.Paragraph()
|
||||
};
|
||||
}
|
||||
|
||||
ReportSectionMap GetMapElement()
|
||||
{
|
||||
var rnd = Helpers.Random.Next(0, 64);
|
||||
|
||||
return new ReportSectionMap
|
||||
{
|
||||
Label = "Location",
|
||||
ImageSource = x => Helpers.GetDocumentMap($"{rnd}.jpg"),
|
||||
ImageSource = Placeholders.Image,
|
||||
Location = Helpers.RandomLocation()
|
||||
};
|
||||
}
|
||||
@@ -98,28 +100,24 @@ namespace QuestPDF.ReportSample
|
||||
{
|
||||
Label = "Photos",
|
||||
Photos = Enumerable
|
||||
.Range(0, Helpers.Random.Next(1, 10))
|
||||
.Select(x => Helpers.Random.Next(0, 128))
|
||||
.Select(x => Helpers.GetPhoto($"{x}.jpg"))
|
||||
.Range(0, Helpers.Random.Next(1, 15))
|
||||
.Select(x => Placeholders.Image(400, 300))
|
||||
.ToList()
|
||||
};
|
||||
}
|
||||
|
||||
ReportPhoto GetReportPhotos()
|
||||
{
|
||||
var photoId = Helpers.Random.Next(0, 128);
|
||||
var mapId = Helpers.Random.Next(0, 64);
|
||||
|
||||
return new ReportPhoto()
|
||||
{
|
||||
PhotoData = Helpers.GetPhoto($"{photoId}.jpg"),
|
||||
PhotoData = Placeholders.Image(800, 600),
|
||||
|
||||
Comments = TextPlaceholder.Paragraph(),
|
||||
Comments = Placeholders.Sentence(),
|
||||
Date = DateTime.Now - TimeSpan.FromDays(Helpers.Random.NextDouble() * 100),
|
||||
Location = Helpers.RandomLocation(),
|
||||
|
||||
MapContextSource = x => Helpers.GetContextMap($"{mapId}.jpg"),
|
||||
MapDetailsSource = x => Helpers.GetDetailsMap($"{mapId}.jpg")
|
||||
MapContextSource = x => Placeholders.Image(400, 300),
|
||||
MapDetailsSource = x => Placeholders.Image(400, 300)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using QuestPDF.ReportSample.Layouts;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace QuestPDF.ReportSample
|
||||
@@ -10,13 +9,7 @@ namespace QuestPDF.ReportSample
|
||||
public static Random Random { get; } = new Random();
|
||||
|
||||
public static string GetTestItem(string path) => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", path);
|
||||
|
||||
public static byte[] GetDocumentMap(string name) => GetImage(Path.Combine("Maps", "Document", name));
|
||||
public static byte[] GetDetailsMap(string name) => GetImage(Path.Combine("Maps", "Details", name));
|
||||
public static byte[] GetContextMap(string name) => GetImage(Path.Combine("Maps", "Context", name));
|
||||
|
||||
public static byte[] GetPhoto(string name) => GetImage(Path.Combine("Photos", name));
|
||||
|
||||
|
||||
public static byte[] GetImage(string name)
|
||||
{
|
||||
var photoPath = GetTestItem(name);
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
using System;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.ReportSample.Layouts
|
||||
{
|
||||
public static class Helpers
|
||||
{
|
||||
static IContainer Cell(this IContainer container, string color)
|
||||
static IContainer Cell(this IContainer container, bool background)
|
||||
{
|
||||
return container
|
||||
.Border(0.5f)
|
||||
.Background(color)
|
||||
.BorderColor(Colors.Grey.Lighten1)
|
||||
.Background(background ? Colors.Grey.Lighten4 : Colors.White)
|
||||
.Padding(5);
|
||||
}
|
||||
|
||||
public static IContainer LightCell(this IContainer container)
|
||||
public static IContainer ValueCell(this IContainer container)
|
||||
{
|
||||
return container.Cell("#0000");
|
||||
return container.Cell(false);
|
||||
}
|
||||
|
||||
public static IContainer DarkCell(this IContainer container)
|
||||
public static IContainer LabelCell(this IContainer container)
|
||||
{
|
||||
return container.Cell("#1000");
|
||||
return container.Cell(true);
|
||||
}
|
||||
|
||||
public static string Format(this Location location)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.ReportSample.Layouts
|
||||
@@ -15,47 +16,45 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
public void Compose(IContainer container)
|
||||
{
|
||||
container
|
||||
.ShowEntire()
|
||||
.Stack(stack =>
|
||||
{
|
||||
stack.Element(PhotoWithMaps);
|
||||
stack.Element(PhotoDetails);
|
||||
stack.Spacing(5);
|
||||
stack.Item().Element(PhotoWithMaps);
|
||||
stack.Item().Element(PhotoDetails);
|
||||
});
|
||||
}
|
||||
|
||||
void PhotoWithMaps(IContainer container)
|
||||
{
|
||||
container
|
||||
.Padding(-3)
|
||||
.PaddingBottom(3)
|
||||
.Row(row =>
|
||||
{
|
||||
row.RelativeColumn(2).Padding(3).Component(new ImageTemplate(Model.PhotoData));
|
||||
row.RelativeColumn(2).AspectRatio(4 / 3f).Image(Placeholders.Image);
|
||||
|
||||
row.RelativeColumn().Stack(stack =>
|
||||
row.RelativeColumn().PaddingLeft(5).Stack(stack =>
|
||||
{
|
||||
stack.Element().Padding(3).Component(new ImageTemplate(Model.MapDetailsSource));
|
||||
stack.Element().Padding(3).Component(new ImageTemplate(Model.MapContextSource));
|
||||
stack.Spacing(7f);
|
||||
|
||||
stack.Item().AspectRatio(4 / 3f).Image(Placeholders.Image);
|
||||
stack.Item().AspectRatio(4 / 3f).Image(Placeholders.Image);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void PhotoDetails(IContainer container)
|
||||
{
|
||||
container.Stack(stack =>
|
||||
container.Border(0.75f).BorderColor(Colors.Grey.Medium).Grid(grid =>
|
||||
{
|
||||
stack.Element().Row(row =>
|
||||
{
|
||||
row.RelativeColumn().DarkCell().Text("Date", Typography.Normal);
|
||||
row.RelativeColumn(2).LightCell().Text(Model.Date?.ToString("g") ?? string.Empty, Typography.Normal);
|
||||
row.RelativeColumn().DarkCell().Text("Location", Typography.Normal);
|
||||
row.RelativeColumn(2).LightCell().Text(Model.Location.Format(), Typography.Normal);
|
||||
});
|
||||
grid.Columns(6);
|
||||
|
||||
stack.Element().Row(row =>
|
||||
{
|
||||
row.RelativeColumn().DarkCell().Text("Comments", Typography.Normal);
|
||||
row.RelativeColumn(5).LightCell().Text(Model.Comments, Typography.Normal);
|
||||
});
|
||||
grid.Item().LabelCell().Text("Date", Typography.Normal);
|
||||
grid.Item(2).ValueCell().Text(Model.Date?.ToString("g") ?? string.Empty, Typography.Normal);
|
||||
grid.Item().LabelCell().Text("Location", Typography.Normal);
|
||||
grid.Item(2).ValueCell().Text(Model.Location.Format(), Typography.Normal);
|
||||
|
||||
grid.Item().LabelCell().Text("Comments", Typography.Normal);
|
||||
grid.Item(5).ValueCell().Text(Model.Comments, Typography.Normal);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.ReportSample.Layouts
|
||||
@@ -17,31 +16,31 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
public void Compose(IContainer container)
|
||||
{
|
||||
container
|
||||
.MinHeight(100)
|
||||
.Section(section =>
|
||||
.EnsureSpace()
|
||||
.Decoration(decoration =>
|
||||
{
|
||||
section
|
||||
decoration
|
||||
.Header()
|
||||
.PaddingBottom(5)
|
||||
.Text(Model.Title, Typography.Headline);
|
||||
|
||||
section.Content().PageableStack(stack =>
|
||||
decoration.Content().Border(0.75f).BorderColor(Colors.Grey.Medium).Stack(stack =>
|
||||
{
|
||||
foreach (var part in Model.Parts)
|
||||
{
|
||||
stack.Element().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.ConstantColumn(150).DarkCell().Text(part.Label, Typography.Normal);
|
||||
var frame = row.RelativeColumn().LightCell();
|
||||
row.ConstantColumn(150).LabelCell().Text(part.Label, Typography.Normal);
|
||||
var frame = row.RelativeColumn().ValueCell();
|
||||
|
||||
if (part is ReportSectionText text)
|
||||
frame.Text(text.Text, Typography.Normal);
|
||||
|
||||
if (part is ReportSectionMap map)
|
||||
frame.Element(container => MapElement(container, map));
|
||||
frame.Element(x => MapElement(x, map));
|
||||
|
||||
if (part is ReportSectionPhotos photos)
|
||||
frame.Element(container => PhotosElement(container, photos));
|
||||
frame.Element(x => PhotosElement(x, photos));
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -56,12 +55,12 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
return;
|
||||
}
|
||||
|
||||
container.Stack(stack =>
|
||||
container.ShowEntire().Stack(stack =>
|
||||
{
|
||||
stack.Spacing(5);
|
||||
|
||||
stack.Element().Component(new ImageTemplate(model.ImageSource));
|
||||
stack.Element().Text(model.Location.Format(), Typography.Normal);
|
||||
stack.Item().MaxWidth(250).AspectRatio(4 / 3f).Image(Placeholders.Image);
|
||||
stack.Item().Text(model.Location.Format(), Typography.Normal);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -73,21 +72,12 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
return;
|
||||
}
|
||||
|
||||
var rowCount = (int) Math.Ceiling(model.Photos.Count / 3f);
|
||||
|
||||
container.Padding(-2).Stack(stack =>
|
||||
container.Debug("Photos").Grid(grid =>
|
||||
{
|
||||
foreach (var rowId in Enumerable.Range(0, rowCount))
|
||||
{
|
||||
stack.Element().Row(row =>
|
||||
{
|
||||
foreach (var id in Enumerable.Range(0, 3))
|
||||
{
|
||||
var data = model.Photos.ElementAtOrDefault(rowId + id);
|
||||
row.RelativeColumn().Padding(2).Component(new ImageTemplate(data));
|
||||
}
|
||||
});
|
||||
}
|
||||
grid.Spacing(5);
|
||||
grid.Columns(3);
|
||||
|
||||
model.Photos.ForEach(x => grid.Item().AspectRatio(4 / 3f).Image(Placeholders.Image));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,79 +18,73 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
{
|
||||
return new DocumentMetadata()
|
||||
{
|
||||
Title = Model.Title,
|
||||
Size = PageSizes.A4
|
||||
Title = Model.Title
|
||||
};
|
||||
}
|
||||
|
||||
public void Compose(IContainer container)
|
||||
public void Compose(IDocumentContainer container)
|
||||
{
|
||||
container
|
||||
.PaddingVertical(40)
|
||||
.PaddingHorizontal(50)
|
||||
|
||||
.Page(page =>
|
||||
{
|
||||
page.Header(ComposeHeader);
|
||||
page.Content(ComposeContent);
|
||||
page.Footer().AlignCenter().PageNumber("Page {number}");
|
||||
page.MarginVertical(40);
|
||||
page.MarginHorizontal(50);
|
||||
|
||||
page.Size(PageSizes.A4);
|
||||
|
||||
page.Header().Element(ComposeHeader);
|
||||
page.Content().Element(ComposeContent);
|
||||
page.Footer().AlignCenter().PageNumber();
|
||||
});
|
||||
}
|
||||
|
||||
private void ComposeHeader(IContainer container)
|
||||
{
|
||||
container.Row(row =>
|
||||
container.Stack(stack =>
|
||||
{
|
||||
row.RelativeColumn().MaxWidth(300).Stack(stack =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
stack.Spacing(5);
|
||||
row.Spacing(50);
|
||||
|
||||
stack
|
||||
.Element()
|
||||
.PaddingBottom(5)
|
||||
.Text(Model.Title, Typography.Title);
|
||||
|
||||
stack.Element().ShowOnce().Stack(table =>
|
||||
{
|
||||
table.Spacing(5);
|
||||
|
||||
foreach (var field in Model.HeaderFields)
|
||||
{
|
||||
table.Element().Row(row =>
|
||||
{
|
||||
row.ConstantColumn(50)
|
||||
.AlignLeft()
|
||||
.Text($"{field.Label}:", Typography.Normal);
|
||||
|
||||
row.RelativeColumn()
|
||||
.PaddingLeft(10)
|
||||
.Text(field.Value, Typography.Normal);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
row.RelativeColumn().PaddingTop(-10).Text(Model.Title, Typography.Title);
|
||||
row.ConstantColumn(150).ExternalLink("https://www.questpdf.com").Image(Model.LogoData);
|
||||
});
|
||||
|
||||
stack.Item().ShowOnce().PaddingVertical(15).Border(1f).BorderColor(Colors.Grey.Lighten1).ExtendHorizontal();
|
||||
|
||||
row.ConstantColumn(150).ExternalLink("https://www.questpdf.com").Image(Model.LogoData);
|
||||
stack.Item().ShowOnce().Grid(grid =>
|
||||
{
|
||||
grid.Columns(2);
|
||||
grid.Spacing(5);
|
||||
|
||||
foreach (var field in Model.HeaderFields)
|
||||
{
|
||||
grid.Item().Stack(row =>
|
||||
{
|
||||
row.Item().AlignLeft().Text(field.Label, Typography.Normal.SemiBold());
|
||||
row.Item().Text(field.Value, Typography.Normal);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void ComposeContent(IContainer container)
|
||||
{
|
||||
container.PaddingVertical(20).PageableStack(stack =>
|
||||
container.PaddingVertical(20).Stack(stack =>
|
||||
{
|
||||
stack.Spacing(20);
|
||||
|
||||
stack.Element().Component(new TableOfContentsTemplate(Model.Sections));
|
||||
stack.Item().Component(new TableOfContentsTemplate(Model.Sections));
|
||||
|
||||
foreach (var section in Model.Sections)
|
||||
stack.Element().Location(section.Title).Component(new SectionTemplate(section));
|
||||
stack.Item().Location(section.Title).Component(new SectionTemplate(section));
|
||||
|
||||
stack.Element().PageBreak();
|
||||
stack.Element().Location("Photos");
|
||||
stack.Item().PageBreak();
|
||||
stack.Item().Location("Photos");
|
||||
|
||||
foreach (var photo in Model.Photos)
|
||||
stack.Element().Component(new PhotoTemplate(photo));
|
||||
stack.Item().Component(new PhotoTemplate(photo));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
@@ -18,21 +16,21 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
public void Compose(IContainer container)
|
||||
{
|
||||
container
|
||||
.Section(section =>
|
||||
.Decoration(decoration =>
|
||||
{
|
||||
section
|
||||
decoration
|
||||
.Header()
|
||||
.PaddingBottom(5)
|
||||
.Text("Table of contents", Typography.Headline);
|
||||
|
||||
section.Content().PageableStack(stack =>
|
||||
decoration.Content().Stack(stack =>
|
||||
{
|
||||
stack.Spacing(5);
|
||||
|
||||
for (var i = 0; i < Sections.Count; i++)
|
||||
stack.Element(c => DrawLink(c, i+1, Sections[i].Title));
|
||||
stack.Item().Element(c => DrawLink(c, i+1, Sections[i].Title));
|
||||
|
||||
stack.Element(c => DrawLink(c, Sections.Count+1, "Photos"));
|
||||
stack.Item().Element(c => DrawLink(c, Sections.Count+1, "Photos"));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -45,6 +43,7 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
{
|
||||
row.ConstantColumn(25).Text($"{number}.", Typography.Normal);
|
||||
row.RelativeColumn().Text(locationName, Typography.Normal);
|
||||
row.ConstantColumn(150).AlignRight().PageNumber($"Page {{pdf:{locationName}}}", Typography.Normal.AlignRight());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\Photos\readme.txt" />
|
||||
<Content Include="Resources\**\**">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@@ -29,4 +24,8 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\QuestPDF\QuestPDF.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Logo.png" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
|
Before Width: | Height: | Size: 993 B After Width: | Height: | Size: 993 B |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 17 KiB |