nl.knaw.dans.common.lang.pdf.PdfPageLayouter.java Source code

Java tutorial

Introduction

Here is the source code for nl.knaw.dans.common.lang.pdf.PdfPageLayouter.java

Source

/*******************************************************************************
 * Copyright 2015 DANS - Data Archiving and Networked Services
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package nl.knaw.dans.common.lang.pdf;

import static com.lowagie.text.pdf.ColumnText.showTextAligned;

import java.awt.Color;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import nl.knaw.dans.common.lang.mail.ApplicationMailer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lowagie.text.BadElementException;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.Image;
import com.lowagie.text.Phrase;
import com.lowagie.text.pdf.PdfAction;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfWriter;

public class PdfPageLayouter extends PdfPageEventHelper {

    private static final Logger logger = LoggerFactory.getLogger(ApplicationMailer.class);

    private static final int PAGE_NUMBER_TABLE_WIDTH = 100;
    private static final int HEADER_PADDING = 40;
    private static final int HEADER_POSITION = -10;
    private static final int FOOTER_POSITION = 10;
    private static final int MARGIN_BOTTOM = 72;
    private static final int MARGIN_TOP = 64;
    private static final int MARGIN_LEFT = 36;
    private static final int MARGIN_RIGHT = 36;

    private static final Color BLACK = new Color(0, 0, 0, 64);
    private static final Color BLUE = new Color(0, 0, 255, 64);

    private static final Font FONT = FontFactory.getFont(FontFactory.HELVETICA, 9, Font.NORMAL, BLACK);
    private static final Font AFONT = FontFactory.getFont(FontFactory.HELVETICA, 9, Font.NORMAL, BLUE);

    private static final Phrase TO_FIRST = createPageAction("<<", PdfAction.FIRSTPAGE);
    private static final Phrase TO_PREV = createPageAction("<", PdfAction.PREVPAGE);
    private static final Phrase TO_NEXT = createPageAction(">", PdfAction.NEXTPAGE);
    private static final Phrase TO_LAST = createPageAction(">>", PdfAction.LASTPAGE);

    private Phrase footerPhrase;
    private Image headerImage;

    public class HeaderImageException extends Exception {
        private static final long serialVersionUID = 1L;

        // anyone can catch, only owner can throw
        private HeaderImageException(final String id, final Throwable cause) {
            super(id, cause);
        }
    }

    /**
     * Usage example
     *
     * <pre>
     *   final Document document = new Document();
     *   final PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("doc.pdf"));
     *   writer.setPageEvent(new PdfPageLayouter(document,"footer", new URL("logo.png")));
     * </pre>
     *
     * @param document
     * @param footerText optional text above the page number in the footer of the page
     * @param headerImage optional image for the page header
     * @throws HeaderImageException in case of problems with the image
     */
    public PdfPageLayouter(final Document document, final String footerText, final URL headerImage)
            throws HeaderImageException {
        setFooterText(footerText);
        document.setMargins(MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, MARGIN_BOTTOM);
        setHeaderImage(headerImage);
    }

    public void onStartPage(final PdfWriter writer, final Document document) {
        if (headerImage == null)
            return;

        final float top = document.top();
        final PdfContentByte canvas = writer.getDirectContent();
        float resizeFactor = // TODO make calculation logic clearer
                headerImage.getHeight() / (MARGIN_TOP - HEADER_PADDING);
        final float width = headerImage.getWidth() / resizeFactor;
        final float height = headerImage.getHeight() / resizeFactor;

        try {
            canvas.addImage(headerImage, width, 0, 0, height, MARGIN_LEFT, top - HEADER_POSITION);
        } catch (final Exception cause) {
            logger.error("can't add header image to PDF page " + document.getPageNumber(), cause);
        }

    }

    public void onEndPage(final PdfWriter writer, final Document document) {
        final float bottom = document.bottom();
        final float centerX = getCenterX(document);
        final PdfContentByte canvas = writer.getDirectContent();
        final int rotation = 0;

        final PdfPTable table = new PdfPTable(5);
        table.setTotalWidth(PAGE_NUMBER_TABLE_WIDTH);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        table.getDefaultCell().setBorder(0);

        table.addCell(TO_FIRST);
        table.addCell(TO_PREV);
        table.addCell(new Phrase(new Chunk("" + document.getPageNumber(), FONT)));
        table.addCell(TO_NEXT);
        table.addCell(TO_LAST);

        table.writeSelectedRows(0, -1, centerX - (table.getTotalWidth() / 2), bottom - FOOTER_POSITION, canvas);
        if (footerPhrase == null)
            return;
        showTextAligned(canvas, Element.ALIGN_CENTER, new Phrase(footerPhrase), centerX, bottom - FOOTER_POSITION,
                rotation);
    }

    public void setHeaderImage(final URL url) throws HeaderImageException {
        if (url == null) {
            headerImage = null;
            return;
        }
        try {
            headerImage = Image.getInstance(url);
        } catch (final BadElementException e) {
            throw new HeaderImageException(url.toString(), e);
        } catch (final MalformedURLException e) {
            throw new HeaderImageException(url.toString(), e);
        } catch (final IOException e) {
            throw new HeaderImageException(url.toString(), e);
        }
    }

    public void setFooterText(final String value) {
        if (value == null) {
            footerPhrase = null;
            return;
        }
        footerPhrase = new Phrase(new Chunk(value, FONT));
    }

    private static Phrase createPageAction(final String caption, final int action) {
        return new Phrase(new Chunk(caption, AFONT).setAction(new PdfAction(action)));
    }

    private float getCenterX(final Document document) {
        return (document.right() - document.left()) / 2 + document.leftMargin();
    }
}