Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]
    1   /*
    2    * $Id: PdfPTable.java 3373 2008-05-12 16:21:24Z xlv $
    3    *
    4    * Copyright 2001, 2002 Paulo Soares
    5    *
    6    * The contents of this file are subject to the Mozilla Public License Version 1.1
    7    * (the "License"); you may not use this file except in compliance with the License.
    8    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
    9    *
   10    * Software distributed under the License is distributed on an "AS IS" basis,
   11    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   12    * for the specific language governing rights and limitations under the License.
   13    *
   14    * The Original Code is 'iText, a free JAVA-PDF library'.
   15    *
   16    * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
   17    * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
   18    * All Rights Reserved.
   19    * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
   20    * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
   21    *
   22    * Contributor(s): all the names of the contributors are added in the source code
   23    * where applicable.
   24    *
   25    * Alternatively, the contents of this file may be used under the terms of the
   26    * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
   27    * provisions of LGPL are applicable instead of those above.  If you wish to
   28    * allow use of your version of this file only under the terms of the LGPL
   29    * License and not to allow others to use your version of this file under
   30    * the MPL, indicate your decision by deleting the provisions above and
   31    * replace them with the notice and other provisions required by the LGPL.
   32    * If you do not delete the provisions above, a recipient may use your version
   33    * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
   34    *
   35    * This library is free software; you can redistribute it and/or modify it
   36    * under the terms of the MPL as stated above or under the terms of the GNU
   37    * Library General Public License as published by the Free Software Foundation;
   38    * either version 2 of the License, or any later version.
   39    *
   40    * This library is distributed in the hope that it will be useful, but WITHOUT
   41    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   42    * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
   43    * details.
   44    *
   45    * If you didn't download this code from the following link, you should check if
   46    * you aren't using an obsolete version:
   47    * http://www.lowagie.com/iText/
   48    */
   49   
   50   package com.lowagie.text.pdf;
   51   
   52   import java.util.ArrayList;
   53   
   54   import com.lowagie.text.DocumentException;
   55   import com.lowagie.text.Element;
   56   import com.lowagie.text.ElementListener;
   57   import com.lowagie.text.Image;
   58   import com.lowagie.text.LargeElement;
   59   import com.lowagie.text.Phrase;
   60   import com.lowagie.text.Rectangle;
   61   import com.lowagie.text.pdf.events.PdfPTableEventForwarder;
   62   
   63   /** This is a table that can be put at an absolute position but can also
   64    * be added to the document as the class <CODE>Table</CODE>.
   65    * In the last case when crossing pages the table always break at full rows; if a
   66    * row is bigger than the page it is dropped silently to avoid infinite loops.
   67    * <P>
   68    * A PdfPTableEvent can be associated to the table to do custom drawing
   69    * when the table is rendered.
   70    * @author Paulo Soares (psoares@consiste.pt)
   71    */
   72   
   73   public class PdfPTable implements LargeElement{
   74       
   75       /** The index of the original <CODE>PdfcontentByte</CODE>.
   76        */    
   77       public static final int BASECANVAS = 0;
   78       /** The index of the duplicate <CODE>PdfContentByte</CODE> where the background will be drawn.
   79        */    
   80       public static final int BACKGROUNDCANVAS = 1;
   81       /** The index of the duplicate <CODE>PdfContentByte</CODE> where the border lines will be drawn.
   82        */    
   83       public static final int LINECANVAS = 2;
   84       /** The index of the duplicate <CODE>PdfContentByte</CODE> where the text will be drawn.
   85        */    
   86       public static final int TEXTCANVAS = 3;
   87       
   88       protected ArrayList rows = new ArrayList();
   89       protected float totalHeight = 0;
   90       protected PdfPCell currentRow[];
   91       protected int currentRowIdx = 0;
   92       protected PdfPCell defaultCell = new PdfPCell((Phrase)null);
   93       protected float totalWidth = 0;
   94       protected float relativeWidths[];
   95       protected float absoluteWidths[];
   96       protected PdfPTableEvent tableEvent;
   97       
   98   /** Holds value of property headerRows. */
   99       protected int headerRows;
  100       
  101   /** Holds value of property widthPercentage. */
  102       protected float widthPercentage = 80;
  103       
  104   /** Holds value of property horizontalAlignment. */
  105       private int horizontalAlignment = Element.ALIGN_CENTER;
  106       
  107   /** Holds value of property skipFirstHeader. */
  108       private boolean skipFirstHeader = false;
  109   
  110       protected boolean isColspan = false;
  111       
  112       protected int runDirection = PdfWriter.RUN_DIRECTION_DEFAULT;
  113   
  114       /**
  115        * Holds value of property lockedWidth.
  116        */
  117       private boolean lockedWidth = false;
  118       
  119       /**
  120        * Holds value of property splitRows.
  121        */
  122       private boolean splitRows = true;
  123       
  124   /** The spacing before the table. */
  125       protected float spacingBefore;
  126       
  127   /** The spacing after the table. */
  128       protected float spacingAfter;
  129       
  130       /**
  131        * Holds value of property extendLastRow.
  132        */
  133       private boolean extendLastRow;
  134       
  135       /**
  136        * Holds value of property headersInEvent.
  137        */
  138       private boolean headersInEvent;
  139       
  140       /**
  141        * Holds value of property splitLate.
  142        */
  143       private boolean splitLate = true;
  144       
  145       /**
  146        * Defines if the table should be kept
  147        * on one page if possible
  148        */
  149       private boolean keepTogether;
  150       
  151       /**
  152        * Indicates if the PdfPTable is complete once added to the document.
  153        * @since	iText 2.0.8
  154        */
  155       protected boolean complete = true;
  156       
  157       /**
  158        * Holds value of property footerRows.
  159        */
  160       private int footerRows;
  161       
  162       protected PdfPTable() {
  163       }
  164       
  165       /** Constructs a <CODE>PdfPTable</CODE> with the relative column widths.
  166        * @param relativeWidths the relative column widths
  167        */    
  168       public PdfPTable(float relativeWidths[]) {
  169           if (relativeWidths == null)
  170               throw new NullPointerException("The widths array in PdfPTable constructor can not be null.");
  171           if (relativeWidths.length == 0)
  172               throw new IllegalArgumentException("The widths array in PdfPTable constructor can not have zero length.");
  173           this.relativeWidths = new float[relativeWidths.length];
  174           System.arraycopy(relativeWidths, 0, this.relativeWidths, 0, relativeWidths.length);
  175           absoluteWidths = new float[relativeWidths.length];
  176           calculateWidths();
  177           currentRow = new PdfPCell[absoluteWidths.length];
  178           keepTogether = false;
  179       }
  180       
  181       /** Constructs a <CODE>PdfPTable</CODE> with <CODE>numColumns</CODE> columns.
  182        * @param numColumns the number of columns
  183        */    
  184       public PdfPTable(int numColumns) {
  185           if (numColumns <= 0)
  186               throw new IllegalArgumentException("The number of columns in PdfPTable constructor must be greater than zero.");
  187           relativeWidths = new float[numColumns];
  188           for (int k = 0; k < numColumns; ++k)
  189               relativeWidths[k] = 1;
  190           absoluteWidths = new float[relativeWidths.length];
  191           calculateWidths();
  192           currentRow = new PdfPCell[absoluteWidths.length];
  193           keepTogether = false;
  194       }
  195       
  196       /** Constructs a copy of a <CODE>PdfPTable</CODE>.
  197        * @param table the <CODE>PdfPTable</CODE> to be copied
  198        */    
  199       public PdfPTable(PdfPTable table) {
  200           copyFormat(table);
  201           for (int k = 0; k < currentRow.length; ++k) {
  202               if (table.currentRow[k] == null)
  203                   break;
  204               currentRow[k] = new PdfPCell(table.currentRow[k]);
  205           }
  206           for (int k = 0; k < table.rows.size(); ++k) {
  207               PdfPRow row = (PdfPRow)(table.rows.get(k));
  208               if (row != null)
  209                   row = new PdfPRow(row);
  210               rows.add(row);
  211           }
  212       }
  213       
  214       /**
  215        * Makes a shallow copy of a table (format without content).
  216        * @param table
  217        * @return a shallow copy of the table
  218        */
  219       public static PdfPTable shallowCopy(PdfPTable table) {
  220           PdfPTable nt = new PdfPTable();
  221           nt.copyFormat(table);
  222           return nt;
  223       }
  224   
  225       /**
  226        * Copies the format of the sourceTable without copying the content. 
  227        * @param sourceTable
  228        */
  229       private void copyFormat(PdfPTable sourceTable) {
  230           relativeWidths = new float[sourceTable.relativeWidths.length];
  231           absoluteWidths = new float[sourceTable.relativeWidths.length];
  232           System.arraycopy(sourceTable.relativeWidths, 0, relativeWidths, 0, relativeWidths.length);
  233           System.arraycopy(sourceTable.absoluteWidths, 0, absoluteWidths, 0, relativeWidths.length);
  234           totalWidth = sourceTable.totalWidth;
  235           totalHeight = sourceTable.totalHeight;
  236           currentRowIdx = 0;
  237           tableEvent = sourceTable.tableEvent;
  238           runDirection = sourceTable.runDirection;
  239           defaultCell = new PdfPCell(sourceTable.defaultCell);
  240           currentRow = new PdfPCell[sourceTable.currentRow.length];
  241           isColspan = sourceTable.isColspan;
  242           splitRows = sourceTable.splitRows;
  243           spacingAfter = sourceTable.spacingAfter;
  244           spacingBefore = sourceTable.spacingBefore;
  245           headerRows = sourceTable.headerRows;
  246           footerRows = sourceTable.footerRows;
  247           lockedWidth = sourceTable.lockedWidth;
  248           extendLastRow = sourceTable.extendLastRow;
  249           headersInEvent = sourceTable.headersInEvent;
  250           widthPercentage = sourceTable.widthPercentage;
  251           splitLate = sourceTable.splitLate;
  252           skipFirstHeader = sourceTable.skipFirstHeader;
  253           horizontalAlignment = sourceTable.horizontalAlignment;
  254           keepTogether = sourceTable.keepTogether;
  255           complete = sourceTable.complete;
  256       }
  257   
  258       /** Sets the relative widths of the table.
  259        * @param relativeWidths the relative widths of the table.
  260        * @throws DocumentException if the number of widths is different than the number
  261        * of columns
  262        */    
  263       public void setWidths(float relativeWidths[]) throws DocumentException {
  264           if (relativeWidths.length != this.relativeWidths.length)
  265               throw new DocumentException("Wrong number of columns.");
  266           this.relativeWidths = new float[relativeWidths.length];
  267           System.arraycopy(relativeWidths, 0, this.relativeWidths, 0, relativeWidths.length);
  268           absoluteWidths = new float[relativeWidths.length];
  269           totalHeight = 0;
  270           calculateWidths();
  271           calculateHeights();
  272       }
  273   
  274       /** Sets the relative widths of the table.
  275        * @param relativeWidths the relative widths of the table.
  276        * @throws DocumentException if the number of widths is different than the number
  277        * of columns
  278        */    
  279       public void setWidths(int relativeWidths[]) throws DocumentException {
  280           float tb[] = new float[relativeWidths.length];
  281           for (int k = 0; k < relativeWidths.length; ++k)
  282               tb[k] = relativeWidths[k];
  283           setWidths(tb);
  284       }
  285   
  286       private void calculateWidths() {
  287           if (totalWidth <= 0)
  288               return;
  289           float total = 0;
  290           for (int k = 0; k < absoluteWidths.length; ++k) {
  291               total += relativeWidths[k];
  292           }
  293           for (int k = 0; k < absoluteWidths.length; ++k) {
  294               absoluteWidths[k] = totalWidth * relativeWidths[k] / total;
  295           }
  296       }
  297       
  298       /** Sets the full width of the table.
  299        * @param totalWidth the full width of the table.
  300        */    
  301       public void setTotalWidth(float totalWidth) {
  302           if (this.totalWidth == totalWidth)
  303               return;
  304           this.totalWidth = totalWidth;
  305           totalHeight = 0;
  306           calculateWidths();
  307           calculateHeights();
  308       }
  309   
  310       /** Sets the full width of the table from the absolute column width.
  311        * @param columnWidth the absolute width of each column
  312        * @throws DocumentException if the number of widths is different than the number
  313        * of columns
  314        */    
  315       public void setTotalWidth(float columnWidth[]) throws DocumentException {
  316           if (columnWidth.length != this.relativeWidths.length)
  317               throw new DocumentException("Wrong number of columns.");
  318           totalWidth = 0;
  319           for (int k = 0; k < columnWidth.length; ++k)
  320               totalWidth += columnWidth[k];
  321           setWidths(columnWidth);
  322       }
  323   
  324       /** Sets the percentage width of the table from the absolute column width.
  325        * @param columnWidth the absolute width of each column
  326        * @param pageSize the page size
  327        * @throws DocumentException
  328        */    
  329       public void setWidthPercentage(float columnWidth[], Rectangle pageSize) throws DocumentException {
  330           if (columnWidth.length != this.relativeWidths.length)
  331               throw new IllegalArgumentException("Wrong number of columns.");
  332           float totalWidth = 0;
  333           for (int k = 0; k < columnWidth.length; ++k)
  334               totalWidth += columnWidth[k];
  335           widthPercentage = totalWidth / (pageSize.getRight() - pageSize.getLeft()) * 100f;
  336           setWidths(columnWidth);
  337       }
  338   
  339       /** Gets the full width of the table.
  340        * @return the full width of the table
  341        */    
  342       public float getTotalWidth() {
  343           return totalWidth;
  344       }
  345   
  346       void calculateHeights() {
  347           if (totalWidth <= 0)
  348               return;
  349           totalHeight = 0;
  350           for (int k = 0; k < rows.size(); ++k) {
  351               PdfPRow row = (PdfPRow)rows.get(k);
  352               if (row != null) {
  353                   row.setWidths(absoluteWidths);
  354                   totalHeight += row.getMaxHeights();
  355               }
  356           }
  357       }
  358       
  359       /**
  360        * Calculates the heights of the table.
  361        */
  362       public void calculateHeightsFast() {
  363           if (totalWidth <= 0)
  364               return;
  365           totalHeight = 0;
  366           for (int k = 0; k < rows.size(); ++k) {
  367               PdfPRow row = (PdfPRow)rows.get(k);
  368               if (row != null)
  369                   totalHeight += row.getMaxHeights();
  370           }
  371       }
  372       
  373       /** Gets the default <CODE>PdfPCell</CODE> that will be used as
  374        * reference for all the <CODE>addCell</CODE> methods except
  375        * <CODE>addCell(PdfPCell)</CODE>.
  376        * @return default <CODE>PdfPCell</CODE>
  377        */    
  378       public PdfPCell getDefaultCell() {
  379           return defaultCell;
  380       }
  381       
  382       /** Adds a cell element.
  383        * @param cell the cell element
  384        */    
  385       public void addCell(PdfPCell cell) {
  386           PdfPCell ncell = new PdfPCell(cell);
  387           int colspan = ncell.getColspan();
  388           colspan = Math.max(colspan, 1);
  389           colspan = Math.min(colspan, currentRow.length - currentRowIdx);
  390           ncell.setColspan(colspan);
  391           if (colspan != 1)
  392               isColspan = true;
  393           int rdir = ncell.getRunDirection();
  394           if (rdir == PdfWriter.RUN_DIRECTION_DEFAULT)
  395               ncell.setRunDirection(runDirection);
  396           currentRow[currentRowIdx] = ncell;
  397           currentRowIdx += colspan;
  398           if (currentRowIdx >= currentRow.length) {
  399               if (runDirection == PdfWriter.RUN_DIRECTION_RTL) {
  400                   PdfPCell rtlRow[] = new PdfPCell[absoluteWidths.length];
  401                   int rev = currentRow.length;
  402                   for (int k = 0; k < currentRow.length; ++k) {
  403                       PdfPCell rcell = currentRow[k];
  404                       int cspan = rcell.getColspan();
  405                       rev -= cspan;
  406                       rtlRow[rev] = rcell;
  407                       k += cspan - 1;
  408                   }
  409                   currentRow = rtlRow;
  410               }
  411               PdfPRow row = new PdfPRow(currentRow);
  412               if (totalWidth > 0) {
  413                   row.setWidths(absoluteWidths);
  414                   totalHeight += row.getMaxHeights();
  415               }
  416               rows.add(row);
  417               currentRow = new PdfPCell[absoluteWidths.length];
  418               currentRowIdx = 0;
  419           }
  420       }
  421       
  422       /** Adds a cell element.
  423        * @param text the text for the cell
  424        */    
  425       public void addCell(String text) {
  426           addCell(new Phrase(text));
  427       }
  428       
  429       /**
  430        * Adds a nested table.
  431        * @param table the table to be added to the cell
  432        */    
  433       public void addCell(PdfPTable table) {
  434           defaultCell.setTable(table);
  435           addCell(defaultCell);
  436           defaultCell.setTable(null);
  437       }
  438       
  439       /**
  440        * Adds an Image as Cell.
  441        * @param image the <CODE>Image</CODE> to add to the table. This image will fit in the cell
  442        */    
  443       public void addCell(Image image) {
  444           defaultCell.setImage(image);
  445           addCell(defaultCell);
  446           defaultCell.setImage(null);
  447       }
  448       
  449       /**
  450        * Adds a cell element.
  451        * @param phrase the <CODE>Phrase</CODE> to be added to the cell
  452        */    
  453       public void addCell(Phrase phrase) {
  454           defaultCell.setPhrase(phrase);
  455           addCell(defaultCell);
  456           defaultCell.setPhrase(null);
  457       }
  458       
  459       /**
  460        * Writes the selected rows to the document.
  461        * <P>
  462        * <CODE>canvases</CODE> is obtained from <CODE>beginWritingRows()</CODE>.
  463        * @param rowStart the first row to be written, zero index
  464        * @param rowEnd the last row to be written + 1. If it is -1 all the
  465        * rows to the end are written
  466        * @param xPos the x write coordinate
  467        * @param yPos the y write coordinate
  468        * @param canvases an array of 4 <CODE>PdfContentByte</CODE> obtained from
  469        * <CODE>beginWrittingRows()</CODE>
  470        * @return the y coordinate position of the bottom of the last row
  471        * @see #beginWritingRows(com.lowagie.text.pdf.PdfContentByte)
  472        */    
  473       public float writeSelectedRows(int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte[] canvases) {
  474           return writeSelectedRows(0, -1, rowStart, rowEnd, xPos, yPos, canvases);
  475       }
  476       
  477       /** Writes the selected rows and columns to the document.
  478        * This method does not clip the columns; this is only important
  479        * if there are columns with colspan at boundaries.
  480        * <P>
  481        * <CODE>canvases</CODE> is obtained from <CODE>beginWritingRows()</CODE>.
  482        * <P>
  483        * The table event is only fired for complete rows.
  484        * @param colStart the first column to be written, zero index
  485        * @param colEnd the last column to be written + 1. If it is -1 all the
  486        * columns to the end are written
  487        * @param rowStart the first row to be written, zero index
  488        * @param rowEnd the last row to be written + 1. If it is -1 all the
  489        * rows to the end are written
  490        * @param xPos the x write coordinate
  491        * @param yPos the y write coordinate
  492        * @param canvases an array of 4 <CODE>PdfContentByte</CODE> obtained from
  493        * <CODE>beginWrittingRows()</CODE>
  494        * @return the y coordinate position of the bottom of the last row
  495        * @see #beginWritingRows(com.lowagie.text.pdf.PdfContentByte)
  496        */    
  497       public float writeSelectedRows(int colStart, int colEnd, int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte[] canvases) {
  498           if (totalWidth <= 0)
  499               throw new RuntimeException("The table width must be greater than zero.");
  500           int size = rows.size();
  501           if (rowEnd < 0)
  502               rowEnd = size;
  503           rowEnd = Math.min(rowEnd, size);
  504           if (rowStart < 0)
  505               rowStart = 0;
  506           if (rowStart >= rowEnd)
  507               return yPos;
  508           if (colEnd < 0)
  509               colEnd = absoluteWidths.length;
  510           colEnd = Math.min(colEnd, absoluteWidths.length);
  511           if (colStart < 0)
  512               colStart = 0;
  513           colStart = Math.min(colStart, absoluteWidths.length);
  514           float yPosStart = yPos;
  515           for (int k = rowStart; k < rowEnd; ++k) {
  516               PdfPRow row = (PdfPRow)rows.get(k);
  517               if (row != null) {
  518                   row.writeCells(colStart, colEnd, xPos, yPos, canvases);
  519                   yPos -= row.getMaxHeights();
  520               }
  521           }
  522           if (tableEvent != null && colStart == 0 && colEnd == absoluteWidths.length) {
  523               float heights[] = new float[rowEnd - rowStart + 1];
  524               heights[0] = yPosStart;
  525               for (int k = rowStart; k < rowEnd; ++k) {
  526                   PdfPRow row = (PdfPRow)rows.get(k);
  527                   float hr = 0;
  528                   if (row != null)
  529                       hr = row.getMaxHeights();
  530                   heights[k - rowStart + 1] = heights[k - rowStart] - hr;
  531               }
  532               tableEvent.tableLayout(this, getEventWidths(xPos, rowStart, rowEnd, headersInEvent), heights, headersInEvent ? headerRows : 0, rowStart, canvases);
  533           }
  534           return yPos;
  535       }
  536       
  537       /**
  538        * Writes the selected rows to the document.
  539        * 
  540        * @param rowStart the first row to be written, zero index
  541        * @param rowEnd the last row to be written + 1. If it is -1 all the
  542        * rows to the end are written
  543        * @param xPos the x write coordinate
  544        * @param yPos the y write coordinate
  545        * @param canvas the <CODE>PdfContentByte</CODE> where the rows will
  546        * be written to
  547        * @return the y coordinate position of the bottom of the last row
  548        */    
  549       public float writeSelectedRows(int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte canvas) {
  550           return writeSelectedRows(0, -1, rowStart, rowEnd, xPos, yPos, canvas);
  551       }
  552       
  553       /**
  554        * Writes the selected rows to the document.
  555        * This method clips the columns; this is only important
  556        * if there are columns with colspan at boundaries.
  557        * <P>
  558        * The table event is only fired for complete rows.
  559        * 
  560        * @param colStart the first column to be written, zero index
  561        * @param colEnd the last column to be written + 1. If it is -1 all the
  562        * @param rowStart the first row to be written, zero index
  563        * @param rowEnd the last row to be written + 1. If it is -1 all the
  564        * rows to the end are written
  565        * @param xPos the x write coordinate
  566        * @param yPos the y write coordinate
  567        * @param canvas the <CODE>PdfContentByte</CODE> where the rows will
  568        * be written to
  569        * @return the y coordinate position of the bottom of the last row
  570        */    
  571       public float writeSelectedRows(int colStart, int colEnd, int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte canvas) {
  572           if (colEnd < 0)
  573               colEnd = absoluteWidths.length;
  574           colEnd = Math.min(colEnd, absoluteWidths.length);
  575           if (colStart < 0)
  576               colStart = 0;
  577           colStart = Math.min(colStart, absoluteWidths.length);
  578           if (colStart != 0 || colEnd != absoluteWidths.length) {
  579               float w = 0;
  580               for (int k = colStart; k < colEnd; ++k)
  581                   w += absoluteWidths[k];
  582               canvas.saveState();
  583               float lx = 0;
  584               float rx = 0;
  585               if (colStart == 0)
  586                   lx = 10000;
  587               if (colEnd == absoluteWidths.length)
  588                   rx = 10000;
  589               canvas.rectangle(xPos - lx, -10000, w + lx + rx, 20000);
  590               canvas.clip();
  591               canvas.newPath();
  592           }
  593           PdfContentByte[] canvases = beginWritingRows(canvas);
  594           float y = writeSelectedRows(colStart, colEnd, rowStart, rowEnd, xPos, yPos, canvases);
  595           endWritingRows(canvases);
  596           if (colStart != 0 || colEnd != absoluteWidths.length)
  597               canvas.restoreState();
  598           return y;
  599       }
  600       
  601       /** Gets and initializes the 4 layers where the table is written to. The text or graphics are added to
  602        * one of the 4 <CODE>PdfContentByte</CODE> returned with the following order:<p>
  603        * <ul>
  604        * <li><CODE>PdfPtable.BASECANVAS</CODE> - the original <CODE>PdfContentByte</CODE>. Anything placed here
  605        * will be under the table.
  606        * <li><CODE>PdfPtable.BACKGROUNDCANVAS</CODE> - the layer where the background goes to.
  607        * <li><CODE>PdfPtable.LINECANVAS</CODE> - the layer where the lines go to.
  608        * <li><CODE>PdfPtable.TEXTCANVAS</CODE> - the layer where the text go to. Anything placed here
  609        * will be over the table.
  610        * </ul><p>
  611        * The layers are placed in sequence on top of each other.
  612        * @param canvas the <CODE>PdfContentByte</CODE> where the rows will
  613        * be written to
  614        * @return an array of 4 <CODE>PdfContentByte</CODE>
  615        * @see #writeSelectedRows(int, int, float, float, PdfContentByte[])
  616        */    
  617       public static PdfContentByte[] beginWritingRows(PdfContentByte canvas) {
  618           return new PdfContentByte[]{
  619               canvas,
  620               canvas.getDuplicate(),
  621               canvas.getDuplicate(),
  622               canvas.getDuplicate(),
  623           };
  624       }
  625       
  626       /** Finishes writing the table.
  627        * @param canvases the array returned by <CODE>beginWritingRows()</CODE>
  628        */    
  629       public static void endWritingRows(PdfContentByte[] canvases) {
  630           PdfContentByte canvas = canvases[BASECANVAS];
  631           canvas.saveState();
  632           canvas.add(canvases[BACKGROUNDCANVAS]);
  633           canvas.restoreState();
  634           canvas.saveState();
  635           canvas.setLineCap(2);
  636           canvas.resetRGBColorStroke();
  637           canvas.add(canvases[LINECANVAS]);
  638           canvas.restoreState();
  639           canvas.add(canvases[TEXTCANVAS]);
  640       }
  641       
  642       /** Gets the number of rows in this table.
  643        * @return the number of rows in this table
  644        */    
  645       public int size() {
  646           return rows.size();
  647       }
  648       
  649       /** Gets the total height of the table.
  650        * @return the total height of the table
  651        */    
  652       public float getTotalHeight() {
  653           return totalHeight;
  654       }
  655       
  656       /** Gets the height of a particular row.
  657        * @param idx the row index (starts at 0)
  658        * @return the height of a particular row
  659        */    
  660       public float getRowHeight(int idx) {
  661           if (totalWidth <= 0 || idx < 0 || idx >= rows.size())
  662               return 0;
  663           PdfPRow row = (PdfPRow)rows.get(idx);
  664           if (row == null)
  665               return 0;
  666           return row.getMaxHeights();
  667       }
  668       
  669       /** Gets the height of the rows that constitute the header as defined by
  670        * <CODE>setHeaderRows()</CODE>.
  671        * @return the height of the rows that constitute the header and footer
  672        */    
  673       public float getHeaderHeight() {
  674           float total = 0;
  675           int size = Math.min(rows.size(), headerRows);
  676           for (int k = 0; k < size; ++k) {
  677               PdfPRow row = (PdfPRow)rows.get(k);
  678               if (row != null)
  679                   total += row.getMaxHeights();
  680           }
  681           return total;
  682       }
  683       
  684       /** Gets the height of the rows that constitute the header as defined by
  685        * <CODE>setFooterRows()</CODE>.
  686        * @return the height of the rows that constitute the footer
  687        * @since 2.1.1
  688        */    
  689       public float getFooterHeight() {
  690           float total = 0;
  691           int start = Math.min(0, headerRows - footerRows);
  692           int size = Math.min(rows.size(), footerRows);
  693           for (int k = start; k < size; ++k) {
  694               PdfPRow row = (PdfPRow)rows.get(k);
  695               if (row != null)
  696                   total += row.getMaxHeights();
  697           }
  698           return total;
  699       }
  700       
  701       /** Deletes a row from the table.
  702        * @param rowNumber the row to be deleted
  703        * @return <CODE>true</CODE> if the row was deleted
  704        */    
  705       public boolean deleteRow(int rowNumber) {
  706           if (rowNumber < 0 || rowNumber >= rows.size()) {
  707               return false;
  708           }
  709           if (totalWidth > 0) {
  710               PdfPRow row = (PdfPRow)rows.get(rowNumber);
  711               if (row != null)
  712                   totalHeight -= row.getMaxHeights();
  713           }
  714           rows.remove(rowNumber);
  715           return true;
  716       }
  717       
  718       /** Deletes the last row in the table.
  719        * @return <CODE>true</CODE> if the last row was deleted
  720        */    
  721       public boolean deleteLastRow() {
  722           return deleteRow(rows.size() - 1);
  723       }
  724       
  725       /**
  726        * Removes all of the rows except headers
  727        */
  728       public void deleteBodyRows() {
  729           ArrayList rows2 = new ArrayList();
  730           for (int k = 0; k < headerRows; ++k)
  731               rows2.add(rows.get(k));
  732           rows = rows2;
  733           totalHeight = 0;
  734           if (totalWidth > 0)
  735               totalHeight = getHeaderHeight();
  736       }
  737       
  738       /** Returns the number of columns.
  739        * @return	the number of columns.
  740        * @since	2.1.1
  741        */
  742       public int getNumberOfColumns() {
  743       	return relativeWidths.length;
  744       }
  745   
  746       /** Gets the number of the rows that constitute the header.
  747        * @return the number of the rows that constitute the header
  748        */
  749       public int getHeaderRows() {
  750           return headerRows;
  751       }
  752       
  753       /** Sets the number of the top rows that constitute the header.
  754        * This header has only meaning if the table is added to <CODE>Document</CODE>
  755        * and the table crosses pages.
  756        * @param headerRows the number of the top rows that constitute the header
  757        */
  758       public void setHeaderRows(int headerRows) {
  759           if (headerRows < 0)
  760               headerRows = 0;
  761           this.headerRows = headerRows;
  762       }
  763       
  764       /**
  765        * Gets all the chunks in this element.
  766        *
  767        * @return	an <CODE>ArrayList</CODE>
  768        */
  769       public ArrayList getChunks() {
  770           return new ArrayList();
  771       }
  772       
  773       /**
  774        * Gets the type of the text element.
  775        *
  776        * @return	a type
  777        */
  778       public int type() {
  779           return Element.PTABLE;
  780       }
  781       
  782   	/**
  783   	 * @see com.lowagie.text.Element#isContent()
  784   	 * @since	iText 2.0.8
  785   	 */
  786   	public boolean isContent() {
  787   		return true;
  788   	}
  789   
  790   	/**
  791   	 * @see com.lowagie.text.Element#isNestable()
  792   	 * @since	iText 2.0.8
  793   	 */
  794   	public boolean isNestable() {
  795   		return true;
  796   	}
  797       
  798       /**
  799        * Processes the element by adding it (or the different parts) to an
  800        * <CODE>ElementListener</CODE>.
  801        *
  802        * @param	listener	an <CODE>ElementListener</CODE>
  803        * @return	<CODE>true</CODE> if the element was processed successfully
  804        */
  805       public boolean process(ElementListener listener) {
  806           try {
  807               return listener.add(this);
  808           }
  809           catch(DocumentException de) {
  810               return false;
  811           }
  812       }
  813       
  814       /** Gets the width percentage that the table will occupy in the page.
  815        * @return the width percentage that the table will occupy in the page
  816        */
  817       public float getWidthPercentage() {
  818           return widthPercentage;
  819       }
  820       
  821       /** Sets the width percentage that the table will occupy in the page.
  822        * @param widthPercentage the width percentage that the table will occupy in the page
  823        */
  824       public void setWidthPercentage(float widthPercentage) {
  825           this.widthPercentage = widthPercentage;
  826       }
  827       
  828       /** Gets the horizontal alignment of the table relative to the page.
  829        * @return the horizontal alignment of the table relative to the page
  830        */
  831       public int getHorizontalAlignment() {
  832           return horizontalAlignment;
  833       }
  834       
  835       /** Sets the horizontal alignment of the table relative to the page.
  836        * It only has meaning if the width percentage is less than
  837        * 100%.
  838        * @param horizontalAlignment the horizontal alignment of the table relative to the page
  839        */
  840       public void setHorizontalAlignment(int horizontalAlignment) {
  841           this.horizontalAlignment = horizontalAlignment;
  842       }
  843       
  844       /**
  845        * Gets a row with a given index
  846        * (added by Jin-Hsia Yang).
  847        * @param idx
  848        * @return the row at position idx
  849        */
  850       public PdfPRow getRow(int idx) {
  851           return (PdfPRow)rows.get(idx);
  852       }
  853   
  854       /**
  855        * Gets an arraylist with all the rows in the table.
  856        * @return an arraylist
  857        */
  858       public ArrayList getRows() {
  859           return rows;
  860       }
  861   
  862       /** Sets the table event for this table.
  863        * @param event the table event for this table
  864        */    
  865       public void setTableEvent(PdfPTableEvent event) {
  866       	if (event == null) this.tableEvent = null;
  867       	else if (this.tableEvent == null) this.tableEvent = event;
  868       	else if (this.tableEvent instanceof PdfPTableEventForwarder) ((PdfPTableEventForwarder)this.tableEvent).addTableEvent(event);
  869       	else {
  870       		PdfPTableEventForwarder forward = new PdfPTableEventForwarder();
  871       		forward.addTableEvent(this.tableEvent);
  872       		forward.addTableEvent(event);
  873       		this.tableEvent = forward;
  874       	}
  875       }
  876       
  877       /** Gets the table event for this page.
  878        * @return the table event for this page
  879        */    
  880       public PdfPTableEvent getTableEvent() {
  881           return tableEvent;
  882       }
  883       
  884       /** Gets the absolute sizes of each column width.
  885        * @return he absolute sizes of each column width
  886        */    
  887       public float[] getAbsoluteWidths() {
  888           return absoluteWidths;
  889       }
  890       
  891       float [][] getEventWidths(float xPos, int firstRow, int lastRow, boolean includeHeaders) {
  892           if (includeHeaders) {
  893               firstRow = Math.max(firstRow, headerRows);
  894               lastRow = Math.max(lastRow, headerRows);
  895           }
  896           float widths[][] = new float[(includeHeaders ? headerRows : 0) + lastRow - firstRow][];
  897           if (isColspan) {
  898               int n = 0;
  899               if (includeHeaders) {
  900                   for (int k = 0; k < headerRows; ++k) {
  901                       PdfPRow row = (PdfPRow)rows.get(k);
  902                       if (row == null)
  903                           ++n;
  904                       else
  905                           widths[n++] = row.getEventWidth(xPos);
  906                   }
  907               }
  908               for (; firstRow < lastRow; ++firstRow) {
  909                       PdfPRow row = (PdfPRow)rows.get(firstRow);
  910                       if (row == null)
  911                           ++n;
  912                       else
  913                           widths[n++] = row.getEventWidth(xPos);
  914               }
  915           }
  916           else {
  917               float width[] = new float[absoluteWidths.length + 1];
  918               width[0] = xPos;
  919               for (int k = 0; k < absoluteWidths.length; ++k)
  920                   width[k + 1] = width[k] + absoluteWidths[k];
  921               for (int k = 0; k < widths.length; ++k)
  922                   widths[k] = width;
  923           }
  924           return widths;
  925       }
  926   
  927   
  928       /** Getter for property skipFirstHeader.
  929        * @return Value of property skipFirstHeader.
  930        */
  931       public boolean isSkipFirstHeader() {
  932           return skipFirstHeader;
  933       }
  934       
  935       /** Skips the printing of the first header. Used when printing
  936        * tables in succession belonging to the same printed table aspect.
  937        * @param skipFirstHeader New value of property skipFirstHeader.
  938        */
  939       public void setSkipFirstHeader(boolean skipFirstHeader) {
  940           this.skipFirstHeader = skipFirstHeader;
  941       }
  942   
  943       /**
  944        * Sets the run direction of the contents of the table.
  945        * @param runDirection
  946        */
  947       public void setRunDirection(int runDirection) {
  948           if (runDirection < PdfWriter.RUN_DIRECTION_DEFAULT || runDirection > PdfWriter.RUN_DIRECTION_RTL)
  949               throw new RuntimeException("Invalid run direction: " + runDirection);
  950           this.runDirection = runDirection;
  951       }
  952       
  953       /**
  954        * Returns the run direction of the contents in the table.
  955        * @return One of the following values: PdfWriter.RUN_DIRECTION_DEFAULT, PdfWriter.RUN_DIRECTION_NO_BIDI, PdfWriter.RUN_DIRECTION_LTR or PdfWriter.RUN_DIRECTION_RTL.
  956        */
  957       public int getRunDirection() {
  958           return runDirection;
  959       }
  960       
  961       /**
  962        * Getter for property lockedWidth.
  963        * @return Value of property lockedWidth.
  964        */
  965       public boolean isLockedWidth() {
  966           return this.lockedWidth;
  967       }
  968       
  969       /**
  970        * Uses the value in <CODE>setTotalWidth()</CODE> in <CODE>Document.add()</CODE>.
  971        * @param lockedWidth <CODE>true</CODE> to use the value in <CODE>setTotalWidth()</CODE> in <CODE>Document.add()</CODE>
  972        */
  973       public void setLockedWidth(boolean lockedWidth) {
  974           this.lockedWidth = lockedWidth;
  975       }
  976       
  977       /**
  978        * Gets the split value.
  979        * @return true to split; false otherwise
  980        */
  981       public boolean isSplitRows() {
  982           return this.splitRows;
  983       }
  984       
  985       /**
  986        * When set the rows that won't fit in the page will be split. 
  987        * Note that it takes at least twice the memory to handle a split table row
  988        * than a normal table. <CODE>true</CODE> by default.
  989        * @param splitRows true to split; false otherwise
  990        */
  991       public void setSplitRows(boolean splitRows) {
  992           this.splitRows = splitRows;
  993       }
  994       
  995   /**
  996    * Sets the spacing before this table.
  997    *
  998    * @param	spacing		the new spacing
  999    */
 1000       
 1001       public void setSpacingBefore(float spacing) {
 1002           this.spacingBefore = spacing;
 1003       }
 1004       
 1005   /**
 1006    * Sets the spacing after this table.
 1007    *
 1008    * @param	spacing		the new spacing
 1009    */
 1010       
 1011       public void setSpacingAfter(float spacing) {
 1012           this.spacingAfter = spacing;
 1013       }    
 1014   
 1015   /**
 1016    * Gets the spacing before this table.
 1017    *
 1018    * @return	the spacing
 1019    */
 1020       
 1021       public float spacingBefore() {
 1022           return spacingBefore;
 1023       }
 1024       
 1025   /**
 1026    * Gets the spacing after this table.
 1027    *
 1028    * @return	the spacing
 1029    */
 1030       
 1031       public float spacingAfter() {
 1032           return spacingAfter;
 1033       }    
 1034       
 1035       /**
 1036        *  Gets the value of the last row extension.
 1037        * @return true if the last row will extend; false otherwise
 1038        */
 1039       public boolean isExtendLastRow() {
 1040           return this.extendLastRow;
 1041       }
 1042       
 1043       /**
 1044        * When set the last row will be extended to fill all the remaining space to the
 1045        * bottom boundary.
 1046        * @param extendLastRow true to extend the last row; false otherwise
 1047        */
 1048       public void setExtendLastRow(boolean extendLastRow) {
 1049           this.extendLastRow = extendLastRow;
 1050       }
 1051       
 1052       /**
 1053        * Gets the header status inclusion in PdfPTableEvent.
 1054        * @return true if the headers are included; false otherwise
 1055        */
 1056       public boolean isHeadersInEvent() {
 1057           return this.headersInEvent;
 1058       }
 1059       
 1060       /**
 1061        * When set the PdfPTableEvent will include the headers.
 1062        * @param headersInEvent true to include the headers; false otherwise
 1063        */
 1064       public void setHeadersInEvent(boolean headersInEvent) {
 1065           this.headersInEvent = headersInEvent;
 1066       }
 1067       
 1068       /**
 1069        * Gets the property splitLate.
 1070        * @return the property splitLate
 1071        */
 1072       public boolean isSplitLate() {
 1073           return this.splitLate;
 1074       }
 1075       
 1076       /**
 1077        * If true the row will only split if it's the first one in an empty page.
 1078        * It's true by default.
 1079        *<p>
 1080        * It's only meaningful if setSplitRows(true).
 1081        * @param splitLate the property value
 1082        */
 1083       public void setSplitLate(boolean splitLate) {
 1084           this.splitLate = splitLate;
 1085       }
 1086       
 1087       /**
 1088        * If true the table will be kept on one page if it fits, by forcing a 
 1089        * new page if it doesn't fit on the current page. The default is to
 1090        * split the table over multiple pages.
 1091        *
 1092        * @param p_KeepTogether whether to try to keep the table on one page
 1093        */
 1094       public void setKeepTogether(boolean p_KeepTogether) {
 1095           keepTogether = p_KeepTogether;
 1096       }
 1097        
 1098       public boolean getKeepTogether() {
 1099           return keepTogether;
 1100       }
 1101       
 1102       /**
 1103        * Gets the number of rows in the footer.
 1104        * @return the number of rows in the footer
 1105        */
 1106       public int getFooterRows() {
 1107           return this.footerRows;
 1108       }
 1109       
 1110       /**
 1111        * Sets the number of rows to be used for the footer. The number
 1112        * of footer rows are subtracted from the header rows. For
 1113        * example, for a table with two header rows and one footer row the
 1114        * code would be:
 1115        * <p>
 1116        * <PRE>
 1117        * table.setHeaderRows(3);
 1118        * table.setFooterRows(1);
 1119        * </PRE>
 1120        * <p>
 1121        * Row 0 and 1 will be the header rows and row 2 will be the footer row.
 1122        * @param footerRows the number of rows to be used for the footer
 1123        */
 1124       public void setFooterRows(int footerRows) {
 1125           if (footerRows < 0)
 1126               footerRows = 0;
 1127           this.footerRows = footerRows;
 1128       }
 1129       
 1130       /**
 1131        * Completes the current row with the default cell. An incomplete row will be dropped
 1132        * but calling this method will make sure that it will be present in the table.
 1133        */
 1134       public void completeRow() {
 1135           while (currentRowIdx > 0) {
 1136               addCell(defaultCell);
 1137           }
 1138       }
 1139   	
 1140   	/**
 1141   	 * @since	iText 2.0.8
 1142   	 * @see com.lowagie.text.LargeElement#flushContent()
 1143   	 */
 1144   	public void flushContent() {
 1145   		deleteBodyRows();
 1146   		setSkipFirstHeader(true);
 1147   	}
 1148   
 1149   	/**
 1150        * @since	iText 2.0.8
 1151   	 * @see com.lowagie.text.LargeElement#isComplete()
 1152   	 */
 1153   	public boolean isComplete() {
 1154   		return complete;
 1155   	}
 1156   
 1157   	/**
 1158        * @since	iText 2.0.8
 1159   	 * @see com.lowagie.text.LargeElement#setComplete(boolean)
 1160   	 */
 1161   	public void setComplete(boolean complete) {
 1162   		this.complete = complete;
 1163   	}
 1164   }

Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]