diff --git a/Elwig/Documents/Document.css b/Elwig/Documents/Document.css
index cc52c29..55933fa 100644
--- a/Elwig/Documents/Document.css
+++ b/Elwig/Documents/Document.css
@@ -55,53 +55,6 @@ header .type {
font-weight: normal;
}
-.footer-wrapper {
- position: running(page-footer);
- width: 165mm;
- /* for some reason the position without the following statement changes on the second page */
- border: var(--border-thickness) solid #00000000;
-}
-
-.footer-wrapper.left {
- position: running(page-footer-left);
-}
-
-.pre-footer {
- margin: 1em 0;
- font-size: 10pt;
-}
-
-.pre-footer > * {
- display: inline-block;
- width: 33%;
-}
-
-.pre-footer > *:first-child {
- text-align: left;
-}
-
-.pre-footer > *:nth-child(2) {
- text-align: center;
- font-style: italic;
-}
-
-.pre-footer > *:last-child {
- text-align: right;
- float: right;
-}
-
-.pre-footer .page::after {
- content: "Seite 1 von 1";
-}
-
-footer {
- font-size: 10pt;
- border-top: var(--border-thickness) solid black;
- height: 25mm;
- padding-top: 1mm;
- text-align: center;
-}
-
.hidden {
visibility: hidden;
}
diff --git a/Elwig/Documents/MemberDataSheet.cshtml b/Elwig/Documents/MemberDataSheet.cshtml
index 3a35e82..3adcb63 100644
--- a/Elwig/Documents/MemberDataSheet.cshtml
+++ b/Elwig/Documents/MemberDataSheet.cshtml
@@ -166,7 +166,6 @@
}
@if (areaComs.Count != 0) {
-
Flächenbindungen per @($"{Model.Date:dd.MM.yyyy}")
diff --git a/Elwig/Documents/MemberDataSheet.css b/Elwig/Documents/MemberDataSheet.css
index 75d31c4..59f21b5 100644
--- a/Elwig/Documents/MemberDataSheet.css
+++ b/Elwig/Documents/MemberDataSheet.css
@@ -1,5 +1,6 @@
h2 {
+ margin-top: 0;
margin-bottom: 0.5em !important;
}
@@ -22,9 +23,3 @@ table.area-commitements td.text {
table.area-commitements tr.sum {
font-size: 12pt;
}
-
-@page :not(:first) {
- br.area-commitements {
- display: none;
- }
-}
diff --git a/Elwig/Elwig.csproj b/Elwig/Elwig.csproj
index cf6c5f5..6022c58 100644
--- a/Elwig/Elwig.csproj
+++ b/Elwig/Elwig.csproj
@@ -25,6 +25,9 @@
+
+
+
diff --git a/Elwig/Helpers/Printing/FooterEventHandler.cs b/Elwig/Helpers/Printing/FooterEventHandler.cs
new file mode 100644
index 0000000..5514684
--- /dev/null
+++ b/Elwig/Helpers/Printing/FooterEventHandler.cs
@@ -0,0 +1,176 @@
+using Elwig.Documents;
+using iText.IO.Font.Constants;
+using iText.Kernel.Font;
+using iText.Kernel.Geom;
+using iText.Kernel.Pdf;
+using iText.Kernel.Pdf.Action;
+using iText.Kernel.Pdf.Canvas;
+using iText.Kernel.Pdf.Event;
+using iText.Kernel.Pdf.Xobject;
+using iText.Layout;
+using iText.Layout.Borders;
+using iText.Layout.Element;
+using iText.Layout.Properties;
+using System;
+using System.Collections.Generic;
+
+namespace Elwig.Helpers.Printing {
+ public class FooterEventHandler : AbstractPdfDocumentEventHandler {
+
+ private const float _fontSize = 10;
+ private const float _ptInMm = 2.8346456693f;
+ private const float _placeholderWidth = 50 * _ptInMm;
+
+ private readonly string _date;
+ private readonly string? _center;
+ private readonly bool _doublePaged;
+ private readonly bool _isPreview;
+ private readonly bool _isBusiness;
+ private readonly bool _showFoldMarks;
+ private readonly PdfFont _font;
+ private readonly PdfFont _fontBold;
+ private readonly PdfFont _fontItalic;
+
+ private readonly List _pageNumPlaceholders;
+
+ public int NumberOfPages { get; private set; }
+
+ public FooterEventHandler(Documents.Document? doc = null) {
+ _date = $"{doc?.Date ?? DateOnly.FromDateTime(Utils.Today):dddd, d. MMMM yyyy}";
+ _center = doc?.DocumentId;
+ _doublePaged = doc?.IsDoublePaged ?? false;
+ _isPreview = doc?.IsPreview ?? false;
+ _isBusiness = doc is BusinessDocument;
+ _showFoldMarks = doc?.ShowFoldMarks ?? false;
+ _font = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN);
+ _fontBold = PdfFontFactory.CreateFont(StandardFonts.TIMES_BOLD);
+ _fontItalic = PdfFontFactory.CreateFont(StandardFonts.TIMES_ITALIC);
+ _pageNumPlaceholders = [];
+ }
+
+ protected override void OnAcceptedEvent(AbstractPdfDocumentEvent evt) {
+ if (evt.GetType() == PdfDocumentEvent.END_PAGE) {
+ OnPageEnd((PdfDocumentEvent)evt);
+ } else if (evt.GetType() == PdfDocumentEvent.START_DOCUMENT_CLOSING) {
+ OnDocumentClose((PdfDocumentEvent)evt);
+ }
+ }
+
+ private void OnPageEnd(PdfDocumentEvent evt) {
+ var pdf = evt.GetDocument();
+ var page = evt.GetPage();
+ var pageNum = pdf.GetPageNumber(page);
+
+ var pageSize = page.GetPageSize();
+ float leftX1 = pageSize.GetLeft() + 25 * _ptInMm;
+ float leftX2 = pageSize.GetLeft() + 20 * _ptInMm;
+ float rightX1 = pageSize.GetRight() - 20 * _ptInMm;
+ float rightX2 = pageSize.GetRight() - 25 * _ptInMm;
+ float footerY = pageSize.GetBottom() + 25 * _ptInMm;
+ float y = footerY + _fontSize;
+ float footerWidth = 165 * _ptInMm;
+ float footerHeight = 25 * _ptInMm;
+
+ var pdfCanvas = new PdfCanvas(page.NewContentStreamAfter(), page.GetResources(), pdf);
+ using var canvas = new Canvas(pdfCanvas, pageSize);
+
+ var placeholder = new PdfFormXObject(new Rectangle(0, 0, _placeholderWidth, _fontSize));
+ _pageNumPlaceholders.Add(placeholder);
+
+ var c = App.Client;
+ var dateP = new Paragraph(_date).SetFont(_font).SetFontSize(_fontSize);
+ var centerP = new Paragraph(_center ?? "").SetFont(_fontItalic).SetFontSize(_fontSize);
+ var pageNumP = new Paragraph().Add(new Image(placeholder)).SetFont(_font).SetFontSize(_fontSize);
+
+ if (pageNum == 1) {
+ // First page
+ canvas.ShowTextAligned(dateP, leftX1, y, TextAlignment.LEFT);
+ canvas.ShowTextAligned(centerP, (leftX1 + rightX1) / 2, y, TextAlignment.CENTER);
+ canvas.ShowTextAligned(pageNumP, rightX1, y, TextAlignment.RIGHT);
+
+ var footerP = new Paragraph().SetFont(_font).SetFontSize(_fontSize)
+ .SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.TOP)
+ .SetMargin(0).SetMultipliedLeading(1)
+ .SetWidth(footerWidth).SetHeight(footerHeight).SetPaddingTop(1 * _ptInMm).SetBorderTop(new SolidBorder(0.5f))
+ .Add(c.NameFull);
+ if (_isBusiness) {
+ footerP.Add("\n");
+ footerP.AddAll(Utils.GenerateFooter("\n", " \u00b7 ")
+ .Item(c.Address).Item($"{c.Plz} {c.Ort}").Item("Österreich").Item("Tel.", c.PhoneNr).Item("Fax", c.FaxNr).NextLine()
+ .Item(c.EmailAddress != null ? new Link(c.EmailAddress, PdfAction.CreateURI($"mailto:{Uri.EscapeDataString(c.Name)}%20<{c.EmailAddress}>")) : null)
+ .Item(c.Website != null ? new Link(c.Website, PdfAction.CreateURI($"http://{c.Website}/")) : null)
+ .Item("Betriebs-Nr.", c.LfbisNr).Item("Bio-KSt.", c.OrganicAuthority).NextLine()
+ .Item("UID", c.UstIdNr).Item("BIC", c.Bic).Item("IBAN", c.Iban)
+ .ToLeafElements());
+ }
+ // FIXME links are drawn on next page - move footer into "normal" document creation
+ canvas.ShowTextAligned(footerP, (leftX1 + rightX1) / 2, footerY, TextAlignment.CENTER, VerticalAlignment.TOP);
+ } else if (_doublePaged && (pageNum % 2 == 0)) {
+ // Swap side
+ canvas.ShowTextAligned(pageNumP, leftX2, footerY, TextAlignment.LEFT, VerticalAlignment.TOP);
+ canvas.ShowTextAligned(centerP, (leftX2 + rightX2) / 2, footerY, TextAlignment.CENTER, VerticalAlignment.TOP);
+ canvas.ShowTextAligned(dateP, rightX2, footerY, TextAlignment.RIGHT, VerticalAlignment.TOP);
+ } else {
+ canvas.ShowTextAligned(dateP, leftX1, footerY, TextAlignment.LEFT, VerticalAlignment.TOP);
+ canvas.ShowTextAligned(centerP, (leftX1 + rightX1) / 2, footerY, TextAlignment.CENTER, VerticalAlignment.TOP);
+ canvas.ShowTextAligned(pageNumP, rightX1, footerY, TextAlignment.RIGHT, VerticalAlignment.TOP);
+ }
+
+ if (_showFoldMarks) {
+ var m1 = pageSize.GetTop() - 105 * _ptInMm;
+ var m2 = pageSize.GetTop() - 148.5 * _ptInMm;
+ var m3 = pageSize.GetTop() - 210 * _ptInMm;
+ pdfCanvas.SetLineWidth(0.5f);
+
+ pdfCanvas.MoveTo(0, m1);
+ pdfCanvas.LineTo(10 * _ptInMm, m1);
+ pdfCanvas.MoveTo(pageSize.GetRight(), m1);
+ pdfCanvas.LineTo(pageSize.GetRight() - 10 * _ptInMm, m1);
+
+ pdfCanvas.MoveTo(0, m2);
+ pdfCanvas.LineTo(7 * _ptInMm, m2);
+ pdfCanvas.MoveTo(pageSize.GetRight(), m2);
+ pdfCanvas.LineTo(pageSize.GetRight() - 7 * _ptInMm, m2);
+
+ pdfCanvas.MoveTo(0, m3);
+ pdfCanvas.LineTo(10 * _ptInMm, m3);
+ pdfCanvas.MoveTo(pageSize.GetRight(), m3);
+ pdfCanvas.LineTo(pageSize.GetRight() - 10 * _ptInMm, m3);
+
+ pdfCanvas.ClosePathStroke();
+ }
+
+ if (NumberOfPages > 0) {
+ // FillPlaceholders() was already called
+ FillPlaceholder(pdf, pageNum);
+ }
+ }
+
+ private void OnDocumentClose(PdfDocumentEvent evt) {
+ FillPlaceholders(evt.GetDocument());
+ }
+
+ private void FillPlaceholders(PdfDocument pdf) {
+ NumberOfPages = pdf.GetNumberOfPages();
+ for (int i = 0; i < _pageNumPlaceholders.Count; i++)
+ FillPlaceholder(pdf, i + 1);
+ }
+
+ private void FillPlaceholder(PdfDocument pdf, int pageNum) {
+ var placeholder = _pageNumPlaceholders[pageNum - 1];
+ using var canvas = new Canvas(placeholder, pdf);
+ if (_doublePaged && (pageNum % 2 == 0)) {
+ // swap
+ var p = new Paragraph().SetFont(_font).SetFontSize(_fontSize);
+ if (_isPreview) p.Add(new Text("(vorläufig) ").SetFont(_fontBold));
+ p.Add($"Seite {pageNum:N0} von {NumberOfPages:N0} ");
+ canvas.ShowTextAligned(p, 0, 0, TextAlignment.LEFT);
+ } else {
+ var p = new Paragraph().SetFont(_font).SetFontSize(_fontSize)
+ .Add($"Seite {pageNum:N0} von {NumberOfPages:N0}");
+ if (_isPreview) p.Add(new Text(" (vorläufig)").SetFont(_fontBold));
+ canvas.ShowTextAligned(p, _placeholderWidth, 0, TextAlignment.RIGHT);
+ }
+ }
+ }
+}
diff --git a/Elwig/Helpers/Printing/Pdf.cs b/Elwig/Helpers/Printing/Pdf.cs
index cd253be..28a1d60 100644
--- a/Elwig/Helpers/Printing/Pdf.cs
+++ b/Elwig/Helpers/Printing/Pdf.cs
@@ -1,103 +1,148 @@
using Elwig.Windows;
+using iText.Html2pdf;
+using iText.Kernel.Pdf;
+using iText.Kernel.Pdf.Event;
+using iText.Kernel.Utils;
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
-using System.Net.Sockets;
-using System.Reflection;
-using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace Elwig.Helpers.Printing {
public static class Pdf {
-
- private static readonly string WinziPrint = (Assembly.GetEntryAssembly()?.Location.Contains(@"\bin\") ?? false) ?
- Path.Combine(Assembly.GetEntryAssembly()!.Location.Split(@"\bin\")[0], "../Installer/Files/WinziPrint.exe") :
- new string[] { App.InstallPath }
- .Union(Environment.GetEnvironmentVariable("PATH")?.Split(';') ?? [])
- .Select(x => Path.Combine(x, "WinziPrint.exe"))
- .Where(File.Exists)
- .FirstOrDefault() ?? throw new FileNotFoundException("WiniPrint executable not found");
- private static Process? WinziPrintProc;
- public static bool IsReady => WinziPrintProc != null;
-
- public static async Task Init(Action? evtHandler = null) {
+ public static Task Init(Action? evtHandler = null) {
PdfiumNative.FPDF_InitLibrary();
- // NOTE: If the WinziPrint daemon is already running this will succeed, but the process will fail.
- // Should be no problem, as long as the daemon is not closed
- var p = new Process() { StartInfo = new() {
- FileName = WinziPrint,
- CreateNoWindow = true,
- UseShellExecute = false,
- RedirectStandardOutput = true,
- } };
- p.StartInfo.ArgumentList.Add("-D");
- p.StartInfo.ArgumentList.Add("-d");
- p.StartInfo.ArgumentList.Add(App.TempPath);
- p.Start();
- await p.StandardOutput.ReadLineAsync();
- WinziPrintProc = p;
evtHandler?.Invoke();
+ return Task.CompletedTask;
}
public static Task Cleanup() {
- WinziPrintProc?.Kill(true);
- WinziPrintProc?.Close();
PdfiumNative.FPDF_DestroyLibrary();
return Task.CompletedTask;
}
- public static async Task<(int Pages, IEnumerable PerDoc)> Convert(string htmlPath, string pdfPath, bool doublePaged = false, CancellationToken? cancelToken = null, IProgress? progress = null) {
- return await Convert([htmlPath], pdfPath, doublePaged, cancelToken, progress);
+ public static (int Pages, IEnumerable PerDoc) Convert(string htmlPath, string pdfPath, Documents.Document? doc = null) {
+ int nPages;
+ using var html = File.Open(htmlPath, FileMode.Open);
+ using var writer = new PdfWriter(pdfPath);
+ using var pdf = new PdfDocument(writer);
+ var footerHandler = new FooterEventHandler(doc);
+ pdf.AddEventHandler(PdfDocumentEvent.END_PAGE, footerHandler);
+ pdf.AddEventHandler(PdfDocumentEvent.START_DOCUMENT_CLOSING, footerHandler);
+ // TODO embed fonts?
+ //pdf.AddFont(PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN));
+ HtmlConverter.ConvertToPdf(html, pdf);
+ nPages = footerHandler.NumberOfPages;
+ return (nPages, [nPages]);
}
- public static async Task<(int Pages, IEnumerable PerDoc)> Convert(IEnumerable htmlPath, string pdfPath, bool doublePaged = false, CancellationToken? cancelToken = null, IProgress? progress = null) {
- if (WinziPrintProc == null) throw new InvalidOperationException("The WinziPrint process has not been initialized yet");
- progress?.Report(0.0);
- using var client = new TcpClient("127.0.0.1", 30983);
- using var stream = client.GetStream();
- string cnxId;
- using var reader = new StreamReader(stream);
- var first = await reader.ReadLineAsync() ?? throw new IOException("Invalid response from WinziPrint");
- if (first.StartsWith("id:")) {
- cnxId = first[3..].Trim();
- } else {
- throw new IOException("Invalid response from WinziPrint");
- }
- await stream.WriteAsync(Utils.UTF8.GetBytes(
- "-e utf-8;-p;" + (doublePaged ? "-2;" : "") +
- $"{string.Join(';', htmlPath)};{pdfPath}" +
- "\r\n"));
- bool cancelled = false;
- while (true) {
- if (!cancelled && (cancelToken?.IsCancellationRequested ?? false)) {
- try {
- using var cancelClient = new TcpClient("127.0.0.1", 30983);
- using var cancelStream = cancelClient.GetStream();
- using var cancelReader = new StreamReader(cancelStream);
- await cancelReader.ReadLineAsync();
- await cancelStream.WriteAsync(Utils.UTF8.GetBytes($"cancel;{cnxId}\r\n"));
- } catch { }
- cancelled = true;
+ public static (int Pages, IEnumerable PerDoc) Convert(IEnumerable inputFiles, string pdfPath, bool doublePaged = false, IEnumerable? docs = null, CancellationToken? cancelToken = null, IProgress? progress = null) {
+ var tmpFileNames = new List();
+ var pageNums = new List();
+ var tmpPageNums = new List();
+
+ var htmlFiles = inputFiles
+ .Where(f => !f.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
+ .Select(f => f.TrimStart('!', '#'))
+ .ToList();
+
+ try {
+ for (int i = 0; i < htmlFiles.Count; i++) {
+ string tmpFile = $"{pdfPath}.{i:0000}.part";
+ tmpFileNames.Add(tmpFile);
+ var (pages, _) = Convert(htmlFiles[i], tmpFile, docs?.ElementAt(i));
+ tmpPageNums.Add(pages);
}
- var line = await reader.ReadLineAsync() ?? throw new IOException("Invalid response from WinziPrint");
- if (line.StartsWith("error:")) {
- var msg = line[6..].Trim();
- if (msg == "aborted")
- throw new OperationCanceledException("Dokumentenerzeugung abgebrochen!");
- throw new IOException($"WinziPrint: {msg}");
- } else if (line.StartsWith("progress:")) {
- var parts = line[9..].Trim().Split('/').Select(int.Parse).ToArray();
- progress?.Report(100.0 * parts[0] / parts[1]);
- } else if (line.StartsWith("success:")) {
- var m = Regex.Match(line, @"([0-9]+) pages \(([0-9, ]+)\)");
- return (int.Parse(m.Groups[1].Value), m.Groups[2].Value.Split(", ").Select(int.Parse).ToList());
+
+ using var writer = new PdfWriter(pdfPath);
+ using var mergedPdf = new PdfDocument(writer);
+ var merger = new PdfMerger(mergedPdf);
+
+ PdfPage? letterheadPage = null;
+ int letterheadInsertIndex = 0;
+ int letterheadDocIndex = 0;
+
+ for (int i = 0; i < inputFiles.Count(); i++) {
+ var fileName = inputFiles.ElementAt(i);
+ int p0 = mergedPdf.GetNumberOfPages();
+
+ if (letterheadPage != null && fileName.StartsWith('#')) {
+ if (mergedPdf.GetNumberOfPages() <= letterheadInsertIndex) {
+ mergedPdf.AddPage(letterheadPage.CopyTo(mergedPdf));
+ mergedPdf.AddNewPage();
+ } else {
+ mergedPdf.AddPage(letterheadInsertIndex + 1, letterheadPage.CopyTo(mergedPdf));
+ mergedPdf.AddNewPage(letterheadInsertIndex + 2);
+ }
+
+ pageNums[letterheadDocIndex] = 1;
+ letterheadPage = null;
+ }
+
+ if (fileName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase)) {
+ var cleanName = fileName.TrimStart('!', '#');
+
+ if (doublePaged && fileName.StartsWith('#')) {
+ using var reader = new PdfReader(cleanName);
+ using var src = new PdfDocument(reader);
+ letterheadPage = src.GetPage(1).CopyTo(mergedPdf);
+ letterheadInsertIndex = p0;
+ letterheadDocIndex = i;
+ } else {
+ using var reader = new PdfReader(cleanName);
+ using var src = new PdfDocument(reader);
+ merger.Merge(src, 1, src.GetNumberOfPages());
+ }
+ } else {
+ string tmpFile = tmpFileNames[i];
+ if (doublePaged && fileName.StartsWith('#')) {
+ using var reader = new PdfReader(tmpFile);
+ using var src = new PdfDocument(reader);
+ letterheadPage = src.GetPage(1).CopyTo(mergedPdf);
+ letterheadInsertIndex = p0;
+ letterheadDocIndex = i;
+ } else {
+ using var reader = new PdfReader(tmpFile);
+ using var src = new PdfDocument(reader);
+ merger.Merge(src, 1, tmpPageNums[i]);
+ }
+ }
+
+ int p1 = mergedPdf.GetNumberOfPages();
+ pageNums.Add(p1 - p0);
+
+ if (doublePaged && fileName[0] != '!' && fileName[0] != '#' && mergedPdf.GetNumberOfPages() % 2 != 0) {
+ if (letterheadPage != null) {
+ mergedPdf.AddPage(letterheadPage.CopyTo(mergedPdf));
+ letterheadPage = null;
+ } else {
+ mergedPdf.AddNewPage();
+ }
+ }
+ }
+
+ if (letterheadPage != null) {
+ if (mergedPdf.GetNumberOfPages() <= letterheadInsertIndex) {
+ mergedPdf.AddPage(letterheadPage.CopyTo(mergedPdf));
+ mergedPdf.AddNewPage();
+ } else {
+ mergedPdf.AddPage(letterheadInsertIndex + 1, letterheadPage.CopyTo(mergedPdf));
+ mergedPdf.AddNewPage(letterheadInsertIndex + 2);
+ }
+
+ pageNums[letterheadDocIndex] = 1;
+ }
+ } finally {
+ foreach (var tmp in tmpFileNames) {
+ if (File.Exists(tmp)) File.Delete(tmp);
}
}
+
+ return (pageNums.Sum(), pageNums);
}
public static void Show(TempFile file, string title) {
diff --git a/Elwig/Helpers/Utils.cs b/Elwig/Helpers/Utils.cs
index ff9b91d..eb187ad 100644
--- a/Elwig/Helpers/Utils.cs
+++ b/Elwig/Helpers/Utils.cs
@@ -3,6 +3,7 @@ using Elwig.Documents;
using Elwig.Helpers.Billing;
using Elwig.Models;
using Elwig.Models.Entities;
+using iText.Layout.Element;
using LinqKit;
using MailKit.Net.Smtp;
using MailKit.Security;
@@ -304,23 +305,18 @@ namespace Elwig.Helpers {
}
public class Footer {
- private string Text = "";
+ private readonly List> Items = [[]];
private readonly string LineBreak;
- private readonly string Seperator;
- private bool FirstLine = true;
- private bool FirstItemInLine = true;
+ private readonly string Separator;
- public Footer(string lineBreak, string seperator) {
+ public Footer(string lineBreak, string separator) {
LineBreak = lineBreak;
- Seperator = seperator;
+ Separator = separator;
}
- public Footer Item(string? text) {
+ public Footer Item(object? text) {
if (text == null) return this;
- Text += FirstItemInLine ? (FirstLine ? "" : LineBreak) : Seperator;
- Text += text;
- FirstLine = false;
- FirstItemInLine = false;
+ Items[^1].Add(text);
return this;
}
@@ -329,12 +325,28 @@ namespace Elwig.Helpers {
}
public Footer NextLine() {
- FirstItemInLine = true;
+ Items.Add([]);
return this;
}
public override string ToString() {
- return Text;
+ return string.Join(LineBreak, Items.Select(l => string.Join(Separator, l.ToString())));
+ }
+
+ public IList ToLeafElements() {
+ var l = new List();
+ var first1 = true;
+ foreach (var line in Items) {
+ if (!first1) l.Add(new Text(LineBreak));
+ var first2 = true;
+ foreach (var item in line) {
+ if (!first2) l.Add(new Text(Separator));
+ l.Add(item as ILeafElement ?? new Text(item.ToString()));
+ first2 = false;
+ }
+ first1 = false;
+ }
+ return l;
}
}
diff --git a/Elwig/Windows/AboutWindow.xaml b/Elwig/Windows/AboutWindow.xaml
index edb7c7e..161cb9d 100644
--- a/Elwig/Windows/AboutWindow.xaml
+++ b/Elwig/Windows/AboutWindow.xaml
@@ -22,7 +22,7 @@
Programmiersprache: C#
Framework: Windows Presentation Framework (WPF)
Datenbank: SQLite
- PDF-Erstellung: WeasyPrint, RazorLight, Pdfium
+ PDF-Erstellung: iText, RazorLight, Pdfium
Paketierung: WiX Toolset
diff --git a/Installer/Files/WinziPrint.exe b/Installer/Files/WinziPrint.exe
deleted file mode 100644
index eeba62a..0000000
Binary files a/Installer/Files/WinziPrint.exe and /dev/null differ
diff --git a/Installer/Installer.wixproj b/Installer/Installer.wixproj
index 94511f1..d1d24f9 100644
--- a/Installer/Installer.wixproj
+++ b/Installer/Installer.wixproj
@@ -35,6 +35,5 @@
-
diff --git a/Installer/MainComponents.wxs b/Installer/MainComponents.wxs
index 8322ba4..acf9adb 100644
--- a/Installer/MainComponents.wxs
+++ b/Installer/MainComponents.wxs
@@ -7,9 +7,6 @@
-
-
-
diff --git a/README.md b/README.md
index e7a2d0e..5be4471 100644
--- a/README.md
+++ b/README.md
@@ -43,5 +43,5 @@ Packaging: [WiX Toolset](https://www.firegiant.com/wixtoolset/)
Programmiersprache: C#
Framework: Windows Presentation Framework (WPF)
Datenbank: [SQLite](https://sqlite.org/)
-PDF-Erstellung: [WeasyPrint](https://weasyprint.org/), [RazorLight](https://github.com/toddams/RazorLight), [Pdfium](https://github.com/bblanchon/pdfium-binaries)
+PDF-Erstellung: [iText](https://itextpdf.com/), [RazorLight](https://github.com/toddams/RazorLight), [Pdfium](https://github.com/bblanchon/pdfium-binaries)
Paketierung: [WiX Toolset](https://www.firegiant.com/wixtoolset/)