Java tutorial
/* * Copyright 2015 uia.pdf * * 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 uia.pdf.grid; import java.awt.Color; import java.awt.Point; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode; import org.apache.pdfbox.pdmodel.font.PDFont; import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem; import uia.pdf.ContentView; import uia.pdf.PDFMaker; import uia.pdf.PDFUtil; import uia.pdf.grid.ColumnModel.AlignmentType; import uia.pdf.papers.Paper; /** * Present content with grid. * * @author Kan Lin * */ public class GridView extends ContentView implements AbstractGridView { private final GridModel model; private int rowV; private int tableTop; private int columnH; private boolean columnEachPage; private int fontSize; private PDPage currPage; private boolean drawColumn; public GridView(PDFMaker pdf, Paper paper, GridModel model) { super(pdf, paper); this.model = model; this.columnEachPage = true; this.fontSize = model.getFontSize(); this.drawColumn = model.isHeaderVisible(); } private GridView(PDFMaker pdf, Paper paper, GridModel model, int rowV, int tableTop, int columnH, boolean columnEachPage, PDPage currPage) { super(pdf, paper); this.model = model; this.columnEachPage = columnEachPage; this.fontSize = model.getFontSize(); this.drawColumn = model.isHeaderVisible(); this.rowV = rowV; this.tableTop = tableTop; this.columnH = columnH; this.currPage = currPage; } public boolean isDrawColumn() { return this.drawColumn; } public void setDrawColumn(boolean drawColumn) { this.drawColumn = drawColumn; } public GridView create(GridModel model) { GridView gv = new GridView(this.pdf, this.paper, model, this.rowV, this.tableTop, this.columnH, this.columnEachPage, this.currPage); gv.setHeaderView(getHeaderView()); gv.setFooterView(getFooterView()); return gv; } public boolean isColumnEachPage() { return this.columnEachPage; } public void setColumnEachPage(boolean columnEachPage) { this.columnEachPage = columnEachPage; } @Override public int getFontSize() { return this.fontSize; } public void setFontSize(int fontSize) { this.fontSize = fontSize; } public void endPage() { this.currPage = null; } public void draw(List<Map<String, Object>> data, String bookmark) throws IOException { PDPage page = this.currPage; if (page == null) { page = newPage(); } page = this.pdf.addBookmark(this, page, bookmark); page = drawColumns(page); if (data == null) { return; } int row = 0; for (Map<String, Object> rowCells : data) { page = drawRow(page, rowCells, row, false); } drawGridLine(page); } @Override public PDPage drawBookmarks(PDPage page, List<PDOutlineItem> ois) throws IOException { PDFont font = this.pdf.getFont(); PDPageContentStream contentStream = new PDPageContentStream(this.pdf.getDocument(), page, AppendMode.APPEND, false, false); contentStream.setFont(font, 14); for (PDOutlineItem oi : ois) { if (this.rowV - 16 < getBottom()) { contentStream.close(); page = newPage(); contentStream = new PDPageContentStream(this.pdf.getDocument(), page, AppendMode.APPEND, false, false); contentStream.setFont(font, 14); } contentStream.beginText(); contentStream.newLineAtOffset(getLeft(), this.rowV - 16); contentStream.showText(oi.getTitle().trim()); contentStream.endText(); this.rowV -= 16; } contentStream.close(); this.rowV -= 10; this.tableTop = this.rowV; return page; } private PDPage newPage() { this.rowV = getTop(); this.tableTop = this.rowV; this.columnH = getLeft(); PDPage page = this.paper.createPage(); this.currPage = page; this.pdf.getDocument().addPage(page); this.pages.add(page); return page; } private PDPage drawColumns(PDPage page) throws IOException { if (!this.drawColumn) { return page; } PDFont font = this.pdf.getFont(); ColumnModel[] cms = this.model.getColumnModels(); int hh = 0; for (int i0 = 0; i0 < cms.length; i0++) { ArrayList<String> cs = new ArrayList<String>(); int h0 = PDFUtil.split(cms[i0].getDisplayName(), font, getFontSize(), cms[i0].getWidth() - 4, cs); hh = Math.max(hh, h0); } if (this.rowV - (4 * hh) < getBottom()) { page = newPage(); } PDPageContentStream contentStream = new PDPageContentStream(this.pdf.getDocument(), page, AppendMode.APPEND, false, false); contentStream.setFont(font, this.fontSize); DefaultCellRenderer renderer = new DefaultCellRenderer(); for (int i = 0; i < cms.length; i++) { if (i == 0) { this.columnH = getLeft(); } else { this.columnH += cms[i - 1].getWidth(); } contentStream.setNonStrokingColor(new Color(232, 232, 232)); contentStream.addRect(this.columnH, this.rowV - hh, cms[i].getWidth(), hh); contentStream.fill(); contentStream.setNonStrokingColor(new Color(0, 0, 0)); String content = cms[i].getDisplayName(); int offset = (cms[i].getWidth() - PDFUtil.getContentWidth(content, font, this.fontSize)) / 2; if (this.columnH + offset > getRight()) { break; } ColumnModel other = cms[i].clone(); other.setWrap(true); other.setHorizontalAlignment(AlignmentType.CENTER); other.setBackground(new Color(232, 232, 232)); renderer.paint(contentStream, new Point(this.columnH, this.rowV), this, other, content, -1, i); //contentStream.beginText(); //contentStream.newLineAtOffset(this.columnH + offset, this.rowV - h - 3); //contentStream.showText(content); //contentStream.endText(); } contentStream.moveTo(getLeft(), this.rowV - hh); contentStream.lineTo(getRight(), this.rowV - hh); contentStream.stroke(); this.rowV -= hh; contentStream.close(); return page; } private PDPage drawRow(PDPage page, Map<String, Object> rowCells, int row, boolean forceNewPage) throws IOException { PDPage currPage = page; if (forceNewPage || (this.rowV - 12) < getBottom()) { drawGridLine(page); currPage = newPage(); if (this.columnEachPage) { currPage = drawColumns(currPage); } } PDFont font = this.pdf.getFont(); PDPageContentStream contentStream = new PDPageContentStream(this.pdf.getDocument(), currPage, AppendMode.APPEND, false, false); contentStream.setFont(font, this.fontSize); ColumnModel[] cms = this.model.getColumnModels(); int h = Short.MIN_VALUE; for (int col = 0; col < cms.length; col++) { ColumnModel cm = cms[col]; if (col == 0) { this.columnH = getLeft(); } else { this.columnH += cms[col - 1].getWidth(); } CellRenderer cr = this.model.getCellRenderer(0, col); h = Math.max(h, cr.paint(contentStream, new Point(this.columnH, this.rowV), this, cm, rowCells.get(cm.getId()), row, col)); } this.rowV -= h; // handle overlap at footer area if (!forceNewPage && this.rowV < getBottom()) { contentStream.setNonStrokingColor(Color.white); contentStream.addRect(getLeft(), this.rowV, (float) this.getPaper().getDrawableSize().getWidth(), h); contentStream.fill(); contentStream.setNonStrokingColor(Color.black); contentStream.close(); this.rowV += h; return drawRow(page, rowCells, row, true); } else { contentStream.setLineWidth(0.1f); contentStream.moveTo(getLeft(), this.rowV); contentStream.lineTo(getRight(), this.rowV); contentStream.stroke(); contentStream.close(); } return currPage; } private void drawGridLine(PDPage page) throws IOException { PDPageContentStream contentStream = new PDPageContentStream(this.pdf.getDocument(), page, AppendMode.APPEND, false, false); contentStream.setLineWidth(1.0f); ColumnModel[] cms = this.model.getColumnModels(); int columnH = getLeft(); for (int i = 0; i < cms.length; i++) { columnH += cms[i].getWidth(); contentStream.moveTo(columnH, this.tableTop); contentStream.lineTo(columnH, this.rowV); contentStream.stroke(); } contentStream.addRect(getLeft(), this.rowV, (float) this.getPaper().getDrawableSize().getWidth(), this.tableTop - this.rowV); contentStream.stroke(); contentStream.close(); this.rowV -= 10; } }