Tweaking padding in customer list and update look and feel pdf export

This commit is contained in:
verboomp
2026-02-06 11:09:25 +01:00
parent 9c439e21ee
commit 5e941753e2
4 changed files with 55 additions and 37 deletions

View File

@@ -70,7 +70,8 @@ public class PdfUtils {
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
float contentWidth = pageWidth - 2 * PAGE_MARGIN;
float halfWidth = contentWidth / 2F;
float imageWidth = contentWidth * 0.75F;
float metadataWidth = contentWidth * 0.25F;
try (PDPageContentStream cs = new PDPageContentStream(document, page)) {
float yPosition = pageHeight - 50F;
@@ -87,10 +88,10 @@ public class PdfUtils {
firstPage = false;
}
// Left side: image (50% of content width)
// Left side: image (75% of content width)
float imageX = PAGE_MARGIN;
float imageY = yPosition;
float imageMaxWidth = halfWidth - 10F;
float imageMaxWidth = imageWidth - 10F;
float imageMaxHeight = pageHeight - 2 * PAGE_MARGIN - 40F;
if (picture.getImage() != null) {
@@ -108,30 +109,25 @@ public class PdfUtils {
}
}
// Right side: metadata (top-aligned with image)
float rightX = PAGE_MARGIN + halfWidth + 10F;
float rightY = imageY - 32F;
// Right side: metadata (25% of content width, top-aligned with image)
float rightX = PAGE_MARGIN + imageWidth + 10F;
float rightY = imageY - 10F;
// Date (no label, bold, size 44)
// Date (bold, size 10 - matching labels)
String dateStr = picture.getPictureDate() != null ? (DATE_FORMAT.format(picture.getPictureDate()) + " UHR") : "";
cs.setFont(fontBold, 32);
cs.setFont(fontBold, 10);
cs.setNonStrokingColor(COLOR_DATE);
cs.beginText();
cs.newLineAtOffset(rightX, rightY);
cs.showText(dateStr);
cs.endText();
rightY -= 54F;
rightY -= 24F;
// Customer number
float kundenNummerY = rightY;
rightY = drawLabel(cs, fontBold, "KUNDENNUMMER", rightX, rightY);
rightY = drawValue(cs, fontRegular, nullSafe(customer.getCustomerNumber()), rightX, rightY);
rightY -= 10F;
// Evaluation card with circles
float circlesX = rightX + 140F;
drawEvaluationCard(cs, fontBold, circlesX, kundenNummerY, picture.getEvaluation());
// ZIP
rightY = drawLabel(cs, fontBold, "PLZ", rightX, rightY);
rightY = drawValue(cs, fontRegular, nullSafe(customer.getZip()), rightX, rightY);
@@ -142,9 +138,27 @@ public class PdfUtils {
rightY = drawValue(cs, fontRegular, nullSafe(customer.getCity()), rightX, rightY);
rightY -= 10F;
// Evaluation card with circles
float evaluationY = rightY;
drawEvaluationCard(cs, fontBold, rightX, evaluationY, picture.getEvaluation());
rightY -= 80F;
// Comment
rightY = drawLabel(cs, fontBold, "KOMMENTAR", rightX, rightY);
drawWrappedText(cs, fontRegular, nullSafe(picture.getComment()), rightX, rightY, halfWidth - 20f);
String remainingComment = drawWrappedText(cs, fontRegular, nullSafe(picture.getComment()), rightX, rightY, metadataWidth - 20f, 50F);
// Continue comment on additional pages if needed
while (remainingComment != null && !remainingComment.isEmpty()) {
PDPage continuationPage = new PDPage(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth()));
document.addPage(continuationPage);
try (PDPageContentStream continuationCs = new PDPageContentStream(document, continuationPage)) {
float continuationY = continuationPage.getMediaBox().getHeight() - PAGE_MARGIN;
float continuationWidth = continuationPage.getMediaBox().getWidth() - 2 * PAGE_MARGIN;
continuationY = drawLabel(continuationCs, fontBold, "KOMMENTAR (FORTSETZUNG)", PAGE_MARGIN, continuationY);
remainingComment = drawWrappedText(continuationCs, fontRegular, remainingComment, PAGE_MARGIN, continuationY, continuationWidth, 50F);
}
}
}
}
@@ -189,9 +203,9 @@ public class PdfUtils {
return y - 14F;
}
private void drawWrappedText(PDPageContentStream cs, PDFont font, String text, float x, float y, float maxWidth) throws IOException {
private String drawWrappedText(PDPageContentStream cs, PDFont font, String text, float x, float y, float maxWidth, float minY) throws IOException {
if (text == null || text.isEmpty()) {
return;
return null;
}
cs.setFont(font, 10);
cs.setNonStrokingColor(COLOR_TEXT_GRAY);
@@ -199,11 +213,23 @@ public class PdfUtils {
String[] words = text.split("\\s+");
StringBuilder line = new StringBuilder();
float currentY = y;
int wordIndex = 0;
for (String word : words) {
for (wordIndex = 0; wordIndex < words.length; wordIndex++) {
String word = words[wordIndex];
String testLine = line.isEmpty() ? word : (line + " " + word);
float textWidth = font.getStringWidth(testLine) / 1000F * 10F;
if (textWidth > maxWidth && !line.isEmpty()) {
// Check if we have room for this line
if (currentY < minY) {
// Return remaining text starting from current word
StringBuilder remaining = new StringBuilder(line);
for (int i = wordIndex; i < words.length; i++) {
if (!remaining.isEmpty()) remaining.append(" ");
remaining.append(words[i]);
}
return remaining.toString();
}
cs.beginText();
cs.newLineAtOffset(x, currentY);
cs.showText(line.toString());
@@ -215,45 +241,36 @@ public class PdfUtils {
}
}
if (!line.isEmpty()) {
if (currentY < minY) {
return line.toString();
}
cs.beginText();
cs.newLineAtOffset(x, currentY);
cs.showText(line.toString());
cs.endText();
}
return null;
}
private void drawEvaluationCard(PDPageContentStream cs, PDFont fontBold, float x, float y, Integer evaluation) throws IOException {
int eval = evaluation != null ? evaluation : 0;
Color[] colors = { COLOR_GREEN, COLOR_YELLOW, COLOR_RED };
float cardPadding = 10F;
float cardWidth = 2 * CIRCLE_SPACING + 2 * HIGHLIGHT_RADIUS + 2 * cardPadding;
float labelHeight = 14F;
float cardHeight = labelHeight + 2 * HIGHLIGHT_RADIUS + 2 * cardPadding + 4F;
float cardX = x - HIGHLIGHT_RADIUS - cardPadding;
float cardY = y - cardHeight + cardPadding;
// Draw card background (rounded rectangle)
cs.setStrokingColor(new Color(0xDD, 0xDD, 0xDD));
cs.setNonStrokingColor(new Color(0xF8, 0xF8, 0xF8));
cs.setLineWidth(1f);
drawRoundedRect(cs, cardX, cardY, cardWidth, cardHeight, 6F);
cs.fillAndStroke();
// Draw "BEWERTUNG" label above circles
float labelX = x;
float labelY = y - labelHeight;
cs.setFont(fontBold, 9);
cs.setFont(fontBold, 10);
cs.setNonStrokingColor(COLOR_CUSTOMER_NAME);
cs.beginText();
cs.newLineAtOffset(labelX, labelY);
cs.newLineAtOffset(x, labelY);
cs.showText("BEWERTUNG");
cs.endText();
// Draw circles below the label
float circleY = labelY - cardPadding - HIGHLIGHT_RADIUS - 2F;
float circleY = labelY - HIGHLIGHT_RADIUS - 10F;
for (int i = 0; i < 3; i++) {
float cx = x + i * CIRCLE_SPACING;
float cx = x + CIRCLE_RADIUS + i * CIRCLE_SPACING;
// Highlight circle if this matches the evaluation (1=green, 2=yellow, 3=red)
if (eval == i + 1) {

View File

@@ -78,7 +78,7 @@ class PdfUtilsTest {
byte[] pdfBytes = pdfUtils.createPdf(customer, pictures);
try (PDDocument document = Loader.loadPDF(pdfBytes)) {
assertEquals(3, document.getNumberOfPages());
assertEquals(4, document.getNumberOfPages());
}
writeToFile(pdfBytes, "createPdf_multiplePictures_createsOnPagePerPicture.pdf");
}