177 lines
8.5 KiB
C#
177 lines
8.5 KiB
C#
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<PdfFormXObject> _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);
|
|
}
|
|
}
|
|
}
|
|
}
|