diff --git a/pdf/src/main/java/de/muehlencord/shared/pdf/Content.java b/pdf/src/main/java/de/muehlencord/shared/pdf/Content.java index ad5a8ed..838ffce 100644 --- a/pdf/src/main/java/de/muehlencord/shared/pdf/Content.java +++ b/pdf/src/main/java/de/muehlencord/shared/pdf/Content.java @@ -12,13 +12,14 @@ import org.apache.pdfbox.pdmodel.common.PDRectangle; public abstract class Content { protected PDFDocument document; + protected PDRectangle rect; @Expose protected Integer x; @Expose protected Integer y; - + public Content(PDFDocument document) { this.document = document; this.x = null; @@ -26,7 +27,7 @@ public abstract class Content { } public Content(PDFDocument doc, int x, int y) { - this.document = doc; + this(doc); this.x = x; this.y = y; } @@ -44,7 +45,7 @@ public abstract class Content { } } - protected abstract Coordinate addContentToPdf(PDRectangle rect, PDPageContentStream cos) throws IOException, ConfigurationException; + protected abstract Coordinate addContentToPdf(PDPageContentStream cos) throws IOException, ConfigurationException; /* *** getter / setter *** */ public int getX() { @@ -62,5 +63,12 @@ public abstract class Content { public void setY(int y) { this.y = y; } + + protected PDRectangle getRectangle() { + return rect; + } + protected void setRect(PDRectangle rect) { + this.rect = rect; + } } diff --git a/pdf/src/main/java/de/muehlencord/shared/pdf/DefaultTableRow.java b/pdf/src/main/java/de/muehlencord/shared/pdf/DefaultTableRow.java index e65c1c0..f9f13c3 100644 --- a/pdf/src/main/java/de/muehlencord/shared/pdf/DefaultTableRow.java +++ b/pdf/src/main/java/de/muehlencord/shared/pdf/DefaultTableRow.java @@ -32,8 +32,8 @@ public class DefaultTableRow extends TableRow { public void add(Text text) { row.add(text); - } - + } + /* *** TableRow methods *** */ @Override public int getColumnCount() { diff --git a/pdf/src/main/java/de/muehlencord/shared/pdf/PDFDocument.java b/pdf/src/main/java/de/muehlencord/shared/pdf/PDFDocument.java index 706597f..f70686e 100644 --- a/pdf/src/main/java/de/muehlencord/shared/pdf/PDFDocument.java +++ b/pdf/src/main/java/de/muehlencord/shared/pdf/PDFDocument.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; -import org.apache.commons.lang3.text.StrBuilder; import org.apache.pdfbox.pdmodel.font.PDFont; import org.apache.pdfbox.pdmodel.font.PDType1Font; diff --git a/pdf/src/main/java/de/muehlencord/shared/pdf/PDFTemplate.java b/pdf/src/main/java/de/muehlencord/shared/pdf/PDFTemplate.java index 28d2b73..fe33717 100644 --- a/pdf/src/main/java/de/muehlencord/shared/pdf/PDFTemplate.java +++ b/pdf/src/main/java/de/muehlencord/shared/pdf/PDFTemplate.java @@ -63,14 +63,14 @@ public class PDFTemplate { throw new ConfigurationException("Papersize " + pdfDoc.getPaperSize().getLabel() + " not supported"); } doc.addPage(page); - - PDRectangle rect = page.getMediaBox(); + PDPageContentStream cos = new PDPageContentStream(doc, page, AppendMode.APPEND, false); Coordinate coord = null; for (Content content : pdfDoc.getContentList()) { content.setDocument(pdfDoc); // FIXME move to serialization + content.setRect (page.getMediaBox()); content.setCoordinate(coord); - coord = content.addContentToPdf(rect, cos); + coord = content.addContentToPdf(cos); } cos.close(); doc.save(filenName); diff --git a/pdf/src/main/java/de/muehlencord/shared/pdf/TableContent.java b/pdf/src/main/java/de/muehlencord/shared/pdf/TableContent.java index 341528a..7fff002 100644 --- a/pdf/src/main/java/de/muehlencord/shared/pdf/TableContent.java +++ b/pdf/src/main/java/de/muehlencord/shared/pdf/TableContent.java @@ -6,14 +6,17 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.pdfbox.pdmodel.PDPageContentStream; -import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.font.PDFont; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * * @author jomu */ public class TableContent extends Content { + + private static final Logger LOGGER = LoggerFactory.getLogger(TableContent.class); @Expose private final Font headerFont; @@ -52,6 +55,19 @@ public class TableContent extends Content { return newLine; } + public DefaultTableRow addTextLine(Text... values) { + return addTextLine(Arrays.asList(values)); + } + + public DefaultTableRow addTextLine(List values) { + DefaultTableRow newLine = new DefaultTableRow(); + values.stream().forEach((text) -> { + newLine.add(text); + }); + data.add(newLine); + return newLine; + } + protected TableRow getRow(int no) { return data.get(no); } @@ -61,7 +77,8 @@ public class TableContent extends Content { } @Override - protected Coordinate addContentToPdf(PDRectangle rect, PDPageContentStream cos) throws IOException, ConfigurationException { + protected Coordinate addContentToPdf(PDPageContentStream cos) throws IOException, ConfigurationException { + float margin = 0F; cos.beginText(); PDFont hFont = document.getFont(headerFont.getFontName()); @@ -78,8 +95,10 @@ public class TableContent extends Content { cos.newLineAtOffset(x, y); for (int i = 0; i < header.size(); i++) { cos.showText(header.getHeader(i).getText()); - cos.newLineAtOffset(header.getColumnSize(i), 0); - } + float textWdith = (standardFont.getStringWidth(header.getHeader(i).getText()) / 1000F) * document.getStandardFont().getFontSize(); + LOGGER.info ("Text width for {} = {}", header.getHeader(i).getText(), textWdith); + cos.newLineAtOffset(header.getColumnSize(i), 0); + } if (data.isEmpty()) { currentY -= headerFont.getFontSize() - headerFont.getPadding(); } @@ -90,8 +109,21 @@ public class TableContent extends Content { cos.newLineAtOffset(xOffSet, yOffset); currentY += yOffset; for (int colNo = 0; colNo < currentRow.getColumnCount(); colNo++) { - cos.showText(currentRow.getColumnValue(colNo).getText()); - cos.newLineAtOffset(header.getColumnSize(colNo), 0); + Text currentColText = currentRow.getColumnValue(colNo); + float startX; + if (currentColText.getAlign() == TextAlignment.RIGHT) { + + float textWdith = (standardFont.getStringWidth(currentColText.getText()) / 1000F) * document.getStandardFont().getFontSize(); + float width = header.getColumnSize(colNo) - 2 * margin; + startX = width - textWdith; + LOGGER.info ("Text width for {} = {}", currentColText.getText(), textWdith); + cos.newLineAtOffset(startX, 0); + } else { + startX = 0; + } + + cos.showText(currentColText.getText()); + cos.newLineAtOffset(header.getColumnSize(colNo) - startX, 0); } } currentY += yOffset; diff --git a/pdf/src/main/java/de/muehlencord/shared/pdf/TextContent.java b/pdf/src/main/java/de/muehlencord/shared/pdf/TextContent.java index 9285cfd..1bb867f 100644 --- a/pdf/src/main/java/de/muehlencord/shared/pdf/TextContent.java +++ b/pdf/src/main/java/de/muehlencord/shared/pdf/TextContent.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.util.LinkedList; import java.util.List; import org.apache.pdfbox.pdmodel.PDPageContentStream; -import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.font.PDFont; /** @@ -55,7 +54,7 @@ public class TextContent extends Content { /* *** getter / setter */ @Override - protected Coordinate addContentToPdf(PDRectangle rect, PDPageContentStream cos) throws IOException, ConfigurationException { + protected Coordinate addContentToPdf(PDPageContentStream cos) throws IOException, ConfigurationException { float margin = 40F; cos.beginText(); cos.newLineAtOffset(x, y); diff --git a/pdf/src/test/java/de/muehlencord/shared/pdf/PDFDocumentTest.java b/pdf/src/test/java/de/muehlencord/shared/pdf/PDFDocumentTest.java index 59b4237..22cc759 100644 --- a/pdf/src/test/java/de/muehlencord/shared/pdf/PDFDocumentTest.java +++ b/pdf/src/test/java/de/muehlencord/shared/pdf/PDFDocumentTest.java @@ -17,7 +17,7 @@ import org.junit.Test; */ @FixMethodOrder public class PDFDocumentTest { - + private String jsonString = null; @Test @@ -41,43 +41,55 @@ public class PDFDocumentTest { informationContent.addLine(); informationContent.addLine("Hövelhof, den ${invoiceDate?date}", "bold"); doc.addContent(informationContent); - - TableContent informationContent2 = new TableContent (doc, doc.getStandardFont()); + + TableContent informationContent2 = new TableContent(doc, doc.getStandardFont()); informationContent2.getHeaders() .add("Kunden-Nr", 100) .add("${customerNumber}", 100); - informationContent2.addLine ("Rechnungs-Nr.:", "${invoiceNumber}"); - informationContent2.addLine ("Ausgabe: ", "Dezember"); - informationContent2.addLine ("Rechnungsdatum:", "${invoiceDate?date}"); - doc.addContent(informationContent2); - + informationContent2.addLine("Rechnungs-Nr.:", "${invoiceNumber}"); + informationContent2.addLine("Ausgabe: ", "Dezember"); + informationContent2.addLine("Rechnungsdatum:", "${invoiceDate?date}"); + doc.addContent(informationContent2); + TextContent invoiceInfoInformation = new TextContent(doc, 40, 442, "Sehr geehrter Anzeigenkunde, ") .addLine() .addLine() .addLine("Wir danken für den Auftrag und bitten um Erledigung der folgenden Anzeigenabrechnung", TextAlignment.RIGHT) .addLine(); doc.addContent(invoiceInfoInformation); - + TableContent invoiceLines = new TableContent(doc, doc.getFontByAlias("bold")); invoiceLines.getHeaders() - .add ("Menge", 100) - .add ("Beschreibung", 300) - .add ("Einzelpreis", 100) - .add ("Summe", 100, TextAlignment.RIGHT); - invoiceLines.addLine("1","Anzeige Hövelhofer Rundschau", "10", "10"); - invoiceLines.addLine ("${invoiceline.amount}", "${invoiceline.description}", "${invoiceline.price}", "${invoiceline.total}").createList("invoiceLines", "invoiceline"); - invoiceLines.addLine("2","Anzeige Hövelhofer Rundschau", "10", "20"); - doc.addContent(invoiceLines); - - TextContent test = new TextContent (doc) - .addLine("Das ist ein Test"); - doc.addContent (test); - + .add("Menge", 60) + .add("Beschreibung", 300) + .add(new Text("Einzelpreis", TextAlignment.RIGHT), 80) + .add(new Text("Summe", TextAlignment.RIGHT), 80); + invoiceLines.addTextLine( + new Text("1000", TextAlignment.RIGHT), + new Text("Anzeige Hövelhofer Rundschau"), + new Text("10,00 €", TextAlignment.RIGHT), + new Text("10,00 €", TextAlignment.RIGHT)); + invoiceLines.addTextLine( + new Text("${invoiceline.amount}", TextAlignment.RIGHT), + new Text("${invoiceline.description}"), + new Text("${invoiceline.price}", TextAlignment.RIGHT), + new Text("${invoiceline.total}", TextAlignment.RIGHT)).createList("invoiceLines", "invoiceline"); + invoiceLines.addTextLine( + new Text("2", TextAlignment.RIGHT), + new Text("Anzeige Hövelhofer Rundschau"), + new Text("10,00 €", TextAlignment.RIGHT), + new Text("20,00 €", TextAlignment.RIGHT)); + doc.addContent(invoiceLines); + + TextContent test = new TextContent(doc) + .addLine("Das ist ein Test"); + doc.addContent(test); + jsonString = doc.getTemplateString(); - + File file = new File("c:/temp/test.ftlh"); FileUtils.writeStringToFile(file, jsonString, "UTF-8"); - + // create pdf Configuration cfg = new Configuration(Configuration.VERSION_2_3_24); cfg.setDirectoryForTemplateLoading(new File("c:/temp")); @@ -85,14 +97,14 @@ public class PDFDocumentTest { cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); cfg.setLogTemplateExceptions(false); - Template template = cfg.getTemplate("test.ftlh"); + Template template = cfg.getTemplate("test.ftlh"); PDFTemplate pdfDoc = new PDFTemplate(template); - + Invoice invoice = new Invoice(); - invoice.addInvoiceLine(new InvoiceLine ("Product 1", "10", "1", "10")); - invoice.addInvoiceLine(new InvoiceLine ("Product 2", "5", "10", "50")); - invoice.addInvoiceLine(new InvoiceLine ("Product 3", "100", "20", "2000")); - + invoice.addInvoiceLine(new InvoiceLine("Product 1", "10,00 €", "1", "10,00 €")); + invoice.addInvoiceLine(new InvoiceLine("Product 2", "5,00 €", "10", "50,00 €")); + invoice.addInvoiceLine(new InvoiceLine("Product 3", "100,00 €", "20", "2000,00 €")); + pdfDoc.addToDatamodel("invoiceDate", new Date()); pdfDoc.addToDatamodel("customerNumber", "8755"); pdfDoc.addToDatamodel("invoiceNumber", "1234567");