0001: /*
0002: * $Id: Table.java 2841 2007-06-15 10:00:57Z blowagie $
0003: * $Name$
0004: *
0005: * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
0006: *
0007: * The contents of this file are subject to the Mozilla Public License Version 1.1
0008: * (the "License"); you may not use this file except in compliance with the License.
0009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
0010: *
0011: * Software distributed under the License is distributed on an "AS IS" basis,
0012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013: * for the specific language governing rights and limitations under the License.
0014: *
0015: * The Original Code is 'iText, a free JAVA-PDF library'.
0016: *
0017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
0018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
0019: * All Rights Reserved.
0020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
0021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
0022: *
0023: * Contributor(s): all the names of the contributors are added in the source code
0024: * where applicable.
0025: *
0026: * Alternatively, the contents of this file may be used under the terms of the
0027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
0028: * provisions of LGPL are applicable instead of those above. If you wish to
0029: * allow use of your version of this file only under the terms of the LGPL
0030: * License and not to allow others to use your version of this file under
0031: * the MPL, indicate your decision by deleting the provisions above and
0032: * replace them with the notice and other provisions required by the LGPL.
0033: * If you do not delete the provisions above, a recipient may use your version
0034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE
0035: *
0036: * This library is free software; you can redistribute it and/or modify it
0037: * under the terms of the MPL as stated above or under the terms of the GNU
0038: * Library General Public License as published by the Free Software Foundation;
0039: * either version 2 of the License, or any later version.
0040: *
0041: * This library is distributed in the hope that it will be useful, but WITHOUT
0042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
0043: * FOR A PARTICULAR PURPOSE. See the GNU LIBRARY GENERAL PUBLIC LICENSE for more
0044: * details.
0045: *
0046: * If you didn't download this code from the following link, you should check if
0047: * you aren't using an obsolete version:
0048: * http://www.lowagie.com/iText/
0049: *
0050: * Some methods in this class were contributed by Geert Poels, Kris Jespers and
0051: * Steve Ogryzek. Check the CVS repository.
0052: */
0053:
0054: package com.lowagie.text;
0055:
0056: import java.awt.Color;
0057: import java.awt.Dimension;
0058: import java.awt.Point;
0059: import java.util.ArrayList;
0060: import java.util.Iterator;
0061:
0062: import com.lowagie.text.pdf.PdfPCell;
0063: import com.lowagie.text.pdf.PdfPTable;
0064:
0065: /**
0066: * A <CODE>Table</CODE> is a <CODE>Rectangle</CODE> that contains <CODE>Cell</CODE>s,
0067: * ordered in some kind of matrix.
0068: * <P>
0069: * Tables that span multiple pages are cut into different parts automatically.
0070: * If you want a table header to be repeated on every page, you may not forget to
0071: * mark the end of the header section by using the method <CODE>endHeaders()</CODE>.
0072: * <P>
0073: * The matrix of a table is not necessarily an m x n-matrix. It can contain holes
0074: * or cells that are bigger than the unit. Believe me or not, but it took some serious
0075: * thinking to make this as userfriendly as possible. I hope you wil find the result
0076: * quite simple (I love simple solutions, especially for complex problems).
0077: * I didn't want it to be something as complex as the Java <CODE>GridBagLayout</CODE>.
0078: * <P>
0079: * Example:
0080: * <BLOCKQUOTE><PRE>
0081: * // Remark: You MUST know the number of columns when constructing a Table.
0082: * // The number of rows is not important.
0083: * <STRONG>Table table = new Table(3);</STRONG>
0084: * <STRONG>table.setBorderWidth(1);</STRONG>
0085: * <STRONG>table.setBorderColor(new Color(0, 0, 255));</STRONG>
0086: * <STRONG>table.setPadding(5);</STRONG>
0087: * <STRONG>table.setSpacing(5);</STRONG>
0088: * Cell cell = new Cell("header");
0089: * cell.setHeader(true);
0090: * cell.setColspan(3);
0091: * <STRONG>table.addCell(cell);</STRONG>
0092: * <STRONG>table.endHeaders();</STRONG>
0093: * cell = new Cell("example cell with colspan 1 and rowspan 2");
0094: * cell.setRowspan(2);
0095: * cell.setBorderColor(new Color(255, 0, 0));
0096: * <STRONG>table.addCell(cell);</STRONG>
0097: * <STRONG>table.addCell("1.1");</STRONG>
0098: * <STRONG>table.addCell("2.1");</STRONG>
0099: * <STRONG>table.addCell("1.2");</STRONG>
0100: * <STRONG>table.addCell("2.2");</STRONG>
0101: * <STRONG>table.addCell("cell test1");</STRONG>
0102: * cell = new Cell("big cell");
0103: * cell.setRowspan(2);
0104: * cell.setColspan(2);
0105: * <STRONG>table.addCell(cell);</STRONG>
0106: * <STRONG>table.addCell("cell test2");</STRONG>
0107: * </PRE></BLOCKQUOTE>
0108: * The result of this code is a table:
0109: * <TABLE ALIGN="Center" BORDER="1" BORDERCOLOR="#0000ff" CELLPADDING="5" CELLSPACING="5">
0110: * <TR ALIGN="Left" VALIGN="Left">
0111: * <TH ALIGN="Left" COLSPAN="3" VALIGN="Left">
0112: * header
0113: * </TH>
0114: * </TR>
0115: * <TR ALIGN="Left" VALIGN="Left">
0116: * <TD ALIGN="Left" BORDERCOLOR="#ff0000" ROWSPAN="2" VALIGN="Left">
0117: * example cell with colspan 1 and rowspan 2
0118: * </TD>
0119: * <TD ALIGN="Left" VALIGN="Left">
0120: * 1.1
0121: * </TD>
0122: * <TD ALIGN="Left" VALIGN="Left">
0123: * 2.1
0124: * </TD>
0125: * </TR>
0126: * <TR ALIGN="Left" VALIGN="Left">
0127: * <TD ALIGN="Left" VALIGN="Left">
0128: * 1.2
0129: * </TD>
0130: * <TD ALIGN="Left" VALIGN="Left">
0131: * 2.2
0132: * </TD>
0133: * </TR>
0134: * <TR ALIGN="Left" VALIGN="Left">
0135: * <TD ALIGN="Left" VALIGN="Left">
0136: * cell test1
0137: * </TD>
0138: * <TD ALIGN="Left" COLSPAN="2" ROWSPAN="2" VALIGN="Left">
0139: * big cell
0140: * </TD>
0141: * </TR>
0142: * <TR ALIGN="Left" VALIGN="Left">
0143: * <TD ALIGN="Left" VALIGN="Left">
0144: * cell test2
0145: * </TD>
0146: * </TR>
0147: * </TABLE>
0148: *
0149: * @see Rectangle
0150: * @see Element
0151: * @see Row
0152: * @see Cell
0153: */
0154:
0155: public class Table extends Rectangle {
0156:
0157: // membervariables
0158:
0159: /** This is the number of columns in the <CODE>Table</CODE>. */
0160: private int columns;
0161:
0162: /** This is the list of <CODE>Row</CODE>s. */
0163: private ArrayList rows = new ArrayList();
0164:
0165: /** The current Position in the table. */
0166: private Point curPosition = new Point(0, 0);
0167:
0168: /** This Empty Cell contains the DEFAULT layout of each Cell added with the method addCell(String content). */
0169: private Cell defaultLayout = new Cell(true);
0170:
0171: /** This is the number of the last row of the table headers. */
0172: private int lastHeaderRow = -1;
0173:
0174: /** This is the horizontal alignment. */
0175: private int alignment = Element.ALIGN_CENTER;
0176:
0177: /** This is cellpadding. */
0178: private float cellpadding;
0179:
0180: /** This is cellspacing. */
0181: private float cellspacing;
0182:
0183: /** This is the width of the table (in percent of the available space). */
0184: private float width = 80;
0185:
0186: /** Is the width a percentage (false) or an absolute width (true)? */
0187: private boolean locked = false;
0188:
0189: /** This is an array containing the widths (in percentages) of every column. */
0190: private float[] widths;
0191:
0192: /** Boolean to track if a table was inserted (to avoid unnecessary computations afterwards) */
0193: private boolean mTableInserted = false;
0194:
0195: /**
0196: * Boolean to automatically fill empty cells before a table is rendered
0197: * (takes CPU so may be set to false in case of certainty)
0198: */
0199: protected boolean autoFillEmptyCells = false;
0200:
0201: /** If true this table may not be split over two pages. */
0202: boolean tableFitsPage = false;
0203:
0204: /** If true cells may not be split over two pages. */
0205: boolean cellsFitPage = false;
0206:
0207: /** This is the offset of the table. */
0208: float offset = Float.NaN;
0209:
0210: /** if you want to generate tables the old way, set this value to false. */
0211: protected boolean convert2pdfptable = false;
0212:
0213: // constructors
0214:
0215: /**
0216: * Constructs a <CODE>Table</CODE> with a certain number of columns.
0217: *
0218: * @param columns The number of columns in the table
0219: * @throws BadElementException if the creator was called with less than 1 column
0220: */
0221: public Table(int columns) throws BadElementException {
0222: this (columns, 1);
0223: }
0224:
0225: /**
0226: * Constructs a <CODE>Table</CODE> with a certain number of columns
0227: * and a certain number of <CODE>Row</CODE>s.
0228: *
0229: * @param columns The number of columns in the table
0230: * @param rows The number of rows
0231: * @throws BadElementException if the creator was called with less than 1 column
0232: */
0233: public Table(int columns, int rows) throws BadElementException {
0234: // a Rectangle is create with BY DEFAULT a border with a width of 1
0235: super (0, 0, 0, 0);
0236: setBorder(BOX);
0237: setBorderWidth(1);
0238: defaultLayout.setBorder(BOX);
0239:
0240: // a table should have at least 1 column
0241: if (columns <= 0) {
0242: throw new BadElementException(
0243: "A table should have at least 1 column.");
0244: }
0245: this .columns = columns;
0246:
0247: // a certain number of rows are created
0248: for (int i = 0; i < rows; i++) {
0249: this .rows.add(new Row(columns));
0250: }
0251: curPosition = new Point(0, 0);
0252:
0253: // the DEFAULT widths are calculated
0254: widths = new float[columns];
0255: float width = 100f / columns;
0256: for (int i = 0; i < columns; i++) {
0257: widths[i] = width;
0258: }
0259: }
0260:
0261: /**
0262: * Copy constructor (shallow copy).
0263: * @throws BadElementException
0264: */
0265: public Table(Table t) {
0266: super (0, 0, 0, 0);
0267: this .cloneNonPositionParameters(t);
0268: this .columns = t.columns;
0269: this .rows = t.rows;
0270: this .curPosition = t.curPosition;
0271: this .defaultLayout = t.defaultLayout;
0272: this .lastHeaderRow = t.lastHeaderRow;
0273: this .alignment = t.alignment;
0274: this .cellpadding = t.cellpadding;
0275: this .cellspacing = t.cellspacing;
0276: this .width = t.width;
0277: this .widths = t.widths;
0278: this .autoFillEmptyCells = t.autoFillEmptyCells;
0279: this .tableFitsPage = t.tableFitsPage;
0280: this .cellsFitPage = t.cellsFitPage;
0281: this .offset = t.offset;
0282: this .convert2pdfptable = t.convert2pdfptable;
0283: }
0284:
0285: // implementation of the Element-methods
0286:
0287: /**
0288: * Processes the element by adding it (or the different parts) to an
0289: * <CODE>ElementListener</CODE>.
0290: *
0291: * @param listener an <CODE>ElementListener</CODE>
0292: * @return <CODE>true</CODE> if the element was processed successfully
0293: */
0294: public boolean process(ElementListener listener) {
0295: try {
0296: return listener.add(this );
0297: } catch (DocumentException de) {
0298: return false;
0299: }
0300: }
0301:
0302: /**
0303: * Gets the type of the text element.
0304: *
0305: * @return a type
0306: */
0307: public int type() {
0308: return Element.TABLE;
0309: }
0310:
0311: /**
0312: * Gets all the chunks in this element.
0313: *
0314: * @return an <CODE>ArrayList</CODE>
0315: */
0316:
0317: public ArrayList getChunks() {
0318: return new ArrayList();
0319: }
0320:
0321: // getters and setters
0322:
0323: /**
0324: * Gets the number of columns.
0325: *
0326: * @return a value
0327: */
0328: public int getColumns() {
0329: return columns;
0330: }
0331:
0332: /**
0333: * Gets the number of rows in this <CODE>Table</CODE>.
0334: *
0335: * @return the number of rows in this <CODE>Table</CODE>
0336: */
0337: public int size() {
0338: return rows.size();
0339: }
0340:
0341: /**
0342: * Gets the dimension of this table
0343: *
0344: * @return dimension
0345: */
0346: public Dimension getDimension() {
0347: return new Dimension(columns, size());
0348: }
0349:
0350: /**
0351: * Gets the default layout of the Table.
0352: * @return a cell with all the defaults
0353: */
0354: public Cell getDefaultLayout() {
0355: return defaultLayout;
0356: }
0357:
0358: /**
0359: * Sets the default layout of the Table to
0360: * the provided Cell
0361: * @param value a cell with all the defaults
0362: */
0363: public void setDefaultLayout(Cell value) {
0364: defaultLayout = value;
0365: }
0366:
0367: /**
0368: * Gets the last number of the rows that contain headers.
0369: *
0370: * @return a rownumber
0371: */
0372: public int getLastHeaderRow() {
0373: return this .lastHeaderRow;
0374: }
0375:
0376: /**
0377: * Sets the horizontal alignment.
0378: *
0379: * @param value the new value
0380: */
0381: public void setLastHeaderRow(int value) {
0382: lastHeaderRow = value;
0383: }
0384:
0385: /**
0386: * Marks the last row of the table headers.
0387: *
0388: * @return the number of the last row of the table headers
0389: */
0390: public int endHeaders() {
0391: lastHeaderRow = curPosition.x - 1;
0392: return lastHeaderRow;
0393: }
0394:
0395: /**
0396: * Gets the horizontal alignment.
0397: *
0398: * @return a value
0399: */
0400: public int getAlignment() {
0401: return alignment;
0402: }
0403:
0404: /**
0405: * Sets the horizontal alignment.
0406: *
0407: * @param value the new value
0408: */
0409: public void setAlignment(int value) {
0410: alignment = value;
0411: }
0412:
0413: /**
0414: * Sets the alignment of this paragraph.
0415: *
0416: * @param alignment the new alignment as a <CODE>String</CODE>
0417: */
0418: public void setAlignment(String alignment) {
0419: if (ElementTags.ALIGN_LEFT.equalsIgnoreCase(alignment)) {
0420: this .alignment = Element.ALIGN_LEFT;
0421: return;
0422: }
0423: if (ElementTags.RIGHT.equalsIgnoreCase(alignment)) {
0424: this .alignment = Element.ALIGN_RIGHT;
0425: return;
0426: }
0427: this .alignment = Element.ALIGN_CENTER;
0428: }
0429:
0430: /**
0431: * Gets the cellpadding.
0432: *
0433: * @return a value
0434: */
0435: public float getPadding() {
0436: return cellpadding;
0437: }
0438:
0439: /**
0440: * Sets the cellpadding.
0441: *
0442: * @param value the new value
0443: */
0444: public void setPadding(float value) {
0445: cellpadding = value;
0446: }
0447:
0448: /**
0449: * Gets the cellspacing.
0450: *
0451: * @return a value
0452: */
0453: public float getSpacing() {
0454: return cellspacing;
0455: }
0456:
0457: /**
0458: * Sets the cellspacing.
0459: *
0460: * @param value the new value
0461: */
0462: public void setSpacing(float value) {
0463: cellspacing = value;
0464: }
0465:
0466: /**
0467: * Enables/disables automatic insertion of empty cells before table is rendered. (default = false)
0468: * As some people may want to create a table, fill only a couple of the cells and don't bother with
0469: * investigating which empty ones need to be added, this default behaviour may be very welcome.
0470: * Disabling is recommended to increase speed. (empty cells should be added through extra code then)
0471: *
0472: * @param aDoAutoFill enable/disable autofill
0473: */
0474: public void setAutoFillEmptyCells(boolean aDoAutoFill) {
0475: autoFillEmptyCells = aDoAutoFill;
0476: }
0477:
0478: /**
0479: * Gets the table width (a percentage).
0480: *
0481: * @return the table width
0482: */
0483: public float getWidth() {
0484: return width;
0485: }
0486:
0487: /**
0488: * Sets the width of this table (in percentage of the available space).
0489: *
0490: * @param width the width
0491: */
0492: public void setWidth(float width) {
0493: this .width = width;
0494: }
0495:
0496: /**
0497: * @return the locked
0498: */
0499: public boolean isLocked() {
0500: return locked;
0501: }
0502:
0503: /**
0504: * @param locked the locked to set
0505: */
0506: public void setLocked(boolean locked) {
0507: this .locked = locked;
0508: }
0509:
0510: /**
0511: * Gets the proportional widths of the columns in this <CODE>Table</CODE>.
0512: *
0513: * @return the proportional widths of the columns in this <CODE>Table</CODE>
0514: */
0515: public float[] getProportionalWidths() {
0516: return widths;
0517: }
0518:
0519: /**
0520: * Sets the widths of the different columns (percentages).
0521: * <P>
0522: * You can give up relative values of borderwidths.
0523: * The sum of these values will be considered 100%.
0524: * The values will be recalculated as percentages of this sum.
0525: * <P>
0526: * example:
0527: * <BLOCKQUOTE><PRE>
0528: * float[] widths = {2, 1, 1};
0529: * <STRONG>table.setWidths(widths)</STRONG>
0530: * </PRE></BLOCKQUOTE>
0531: * The widths will be: a width of 50% for the first column,
0532: * 25% for the second and third column.
0533: *
0534: * @param widths an array with values
0535: * @throws BadElementException
0536: */
0537: public void setWidths(float[] widths) throws BadElementException {
0538: if (widths.length != columns) {
0539: throw new BadElementException("Wrong number of columns.");
0540: }
0541:
0542: // The sum of all values is 100%
0543: float hundredPercent = 0;
0544: for (int i = 0; i < columns; i++) {
0545: hundredPercent += widths[i];
0546: }
0547:
0548: // The different percentages are calculated
0549: float width;
0550: this .widths[columns - 1] = 100;
0551: for (int i = 0; i < columns - 1; i++) {
0552: width = (100.0f * widths[i]) / hundredPercent;
0553: this .widths[i] = width;
0554: this .widths[columns - 1] -= width;
0555: }
0556: }
0557:
0558: /**
0559: * Sets the widths of the different columns (percentages).
0560: * <P>
0561: * You can give up relative values of borderwidths.
0562: * The sum of these values will be considered 100%.
0563: * The values will be recalculated as percentages of this sum.
0564: *
0565: * @param widths an array with values
0566: * @throws DocumentException
0567: */
0568: public void setWidths(int[] widths) throws DocumentException {
0569: float tb[] = new float[widths.length];
0570: for (int k = 0; k < widths.length; ++k)
0571: tb[k] = widths[k];
0572: setWidths(tb);
0573: }
0574:
0575: /**
0576: * Checks if this <CODE>Table</CODE> has to fit a page.
0577: *
0578: * @return true if the table may not be split
0579: */
0580: public boolean isTableFitsPage() {
0581: return tableFitsPage;
0582: }
0583:
0584: /**
0585: * Allows you to control when a page break occurs.
0586: * <P>
0587: * When a table doesn't fit a page, it is split in two parts.
0588: * If you want to avoid this, you should set the <VAR>tableFitsPage</VAR> value to true.
0589: *
0590: * @param fitPage enter true if you don't want to split cells
0591: */
0592: public void setTableFitsPage(boolean fitPage) {
0593: this .tableFitsPage = fitPage;
0594: if (fitPage)
0595: setCellsFitPage(true);
0596: }
0597:
0598: /**
0599: * Checks if the cells of this <CODE>Table</CODE> have to fit a page.
0600: *
0601: * @return true if the cells may not be split
0602: */
0603: public boolean isCellsFitPage() {
0604: return cellsFitPage;
0605: }
0606:
0607: /**
0608: * Allows you to control when a page break occurs.
0609: * <P>
0610: * When a cell doesn't fit a page, it is split in two parts.
0611: * If you want to avoid this, you should set the <VAR>cellsFitPage</VAR> value to true.
0612: *
0613: * @param fitPage enter true if you don't want to split cells
0614: */
0615: public void setCellsFitPage(boolean fitPage) {
0616: this .cellsFitPage = fitPage;
0617: }
0618:
0619: /**
0620: * Sets the offset of this table.
0621: *
0622: * Normally a newline is added before you add a Table object.
0623: * This newline uses the current leading.
0624: * If you want to control the space between the table and the previous
0625: * element yourself, you have to set the offset of this table.
0626: *
0627: * @param offset the space between this table and the previous object.
0628: */
0629: public void setOffset(float offset) {
0630: this .offset = offset;
0631: }
0632:
0633: /**
0634: * Gets the offset of this table.
0635: *
0636: * @return the space between this table and the previous element.
0637: */
0638: public float getOffset() {
0639: return offset;
0640: }
0641:
0642: /**
0643: * Method to check if the Table should be converted to a PdfPTable or not.
0644: * @return false if the table should be handled the oldfashioned way.
0645: */
0646: public boolean isConvert2pdfptable() {
0647: return convert2pdfptable;
0648: }
0649:
0650: /**
0651: * If set to true, iText will try to convert the Table to a PdfPTable.
0652: * @param convert2pdfptable true if you want iText to try to convert the Table to a PdfPTable
0653: */
0654: public void setConvert2pdfptable(boolean convert2pdfptable) {
0655: this .convert2pdfptable = convert2pdfptable;
0656: }
0657:
0658: // methods to add content to the table
0659:
0660: /**
0661: * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE> at a certain row and column.
0662: *
0663: * @param aCell The <CODE>Cell</CODE> to add
0664: * @param row The row where the <CODE>Cell</CODE> will be added
0665: * @param column The column where the <CODE>Cell</CODE> will be added
0666: * @throws BadElementException
0667: */
0668: public void addCell(Cell aCell, int row, int column)
0669: throws BadElementException {
0670: addCell(aCell, new Point(row, column));
0671: }
0672:
0673: /**
0674: * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE> at a certain location.
0675: *
0676: * @param aCell The <CODE>Cell</CODE> to add
0677: * @param aLocation The location where the <CODE>Cell</CODE> will be added
0678: * @throws BadElementException
0679: */
0680: public void addCell(Cell aCell, Point aLocation)
0681: throws BadElementException {
0682: if (aCell == null)
0683: throw new NullPointerException(
0684: "addCell - cell has null-value");
0685: if (aLocation == null)
0686: throw new NullPointerException(
0687: "addCell - point has null-value");
0688: if (aCell.isTable())
0689: insertTable((Table) aCell.getElements().next(), aLocation);
0690:
0691: if (aLocation.x < 0)
0692: throw new BadElementException(
0693: "row coordinate of location must be >= 0");
0694: if ((aLocation.y <= 0) && (aLocation.y > columns))
0695: throw new BadElementException(
0696: "column coordinate of location must be >= 0 and < nr of columns");
0697: if (!isValidLocation(aCell, aLocation))
0698: throw new BadElementException(
0699: "Adding a cell at the location ("
0700: + aLocation.x
0701: + ","
0702: + aLocation.y
0703: + ") with a colspan of "
0704: + aCell.getColspan()
0705: + " and a rowspan of "
0706: + aCell.getRowspan()
0707: + " is illegal (beyond boundaries/overlapping).");
0708:
0709: if (aCell.getBorder() == UNDEFINED)
0710: aCell.setBorder(defaultLayout.getBorder());
0711: aCell.fill();
0712: placeCell(rows, aCell, aLocation);
0713: setCurrentLocationToNextValidPosition(aLocation);
0714: }
0715:
0716: /**
0717: * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
0718: *
0719: * @param cell a <CODE>Cell</CODE>
0720: */
0721: public void addCell(Cell cell) {
0722: try {
0723: addCell(cell, curPosition);
0724: } catch (BadElementException bee) {
0725: // don't add the cell
0726: }
0727: }
0728:
0729: /**
0730: * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
0731: * <P>
0732: * This is a shortcut for <CODE>addCell(Cell cell)</CODE>.
0733: * The <CODE>Phrase</CODE> will be converted to a <CODE>Cell</CODE>.
0734: *
0735: * @param content a <CODE>Phrase</CODE>
0736: * @throws BadElementException this should never happen
0737: */
0738: public void addCell(Phrase content) throws BadElementException {
0739: addCell(content, curPosition);
0740: }
0741:
0742: /**
0743: * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
0744: * <P>
0745: * This is a shortcut for <CODE>addCell(Cell cell, Point location)</CODE>.
0746: * The <CODE>Phrase</CODE> will be converted to a <CODE>Cell</CODE>.
0747: *
0748: * @param content a <CODE>Phrase</CODE>
0749: * @param location a <CODE>Point</CODE>
0750: * @throws BadElementException this should never happen
0751: */
0752: public void addCell(Phrase content, Point location)
0753: throws BadElementException {
0754: Cell cell = new Cell(content);
0755: cell.setBorder(defaultLayout.getBorder());
0756: cell.setBorderWidth(defaultLayout.getBorderWidth());
0757: cell.setBorderColor(defaultLayout.getBorderColor());
0758: cell.setBackgroundColor(defaultLayout.getBackgroundColor());
0759: cell.setHorizontalAlignment(defaultLayout
0760: .getHorizontalAlignment());
0761: cell.setVerticalAlignment(defaultLayout.getVerticalAlignment());
0762: cell.setColspan(defaultLayout.getColspan());
0763: cell.setRowspan(defaultLayout.getRowspan());
0764: addCell(cell, location);
0765: }
0766:
0767: /**
0768: * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
0769: * <P>
0770: * This is a shortcut for <CODE>addCell(Cell cell)</CODE>.
0771: * The <CODE>String</CODE> will be converted to a <CODE>Cell</CODE>.
0772: *
0773: * @param content a <CODE>String</CODE>
0774: * @throws BadElementException this should never happen
0775: */
0776:
0777: public void addCell(String content) throws BadElementException {
0778: addCell(new Phrase(content), curPosition);
0779: }
0780:
0781: /**
0782: * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
0783: * <P>
0784: * This is a shortcut for <CODE>addCell(Cell cell, Point location)</CODE>.
0785: * The <CODE>String</CODE> will be converted to a <CODE>Cell</CODE>.
0786: *
0787: * @param content a <CODE>String</CODE>
0788: * @param location a <CODE>Point</CODE>
0789: * @throws BadElementException this should never happen
0790: */
0791: public void addCell(String content, Point location)
0792: throws BadElementException {
0793: addCell(new Phrase(content), location);
0794: }
0795:
0796: /**
0797: * To put a table within the existing table at the current position
0798: * generateTable will of course re-arrange the widths of the columns.
0799: *
0800: * @param aTable the table you want to insert
0801: */
0802: public void insertTable(Table aTable) {
0803: if (aTable == null)
0804: throw new NullPointerException(
0805: "insertTable - table has null-value");
0806: insertTable(aTable, curPosition);
0807: }
0808:
0809: /**
0810: * To put a table within the existing table at the given position
0811: * generateTable will of course re-arrange the widths of the columns.
0812: *
0813: * @param aTable The <CODE>Table</CODE> to add
0814: * @param row The row where the <CODE>Cell</CODE> will be added
0815: * @param column The column where the <CODE>Cell</CODE> will be added
0816: */
0817: public void insertTable(Table aTable, int row, int column) {
0818: if (aTable == null)
0819: throw new NullPointerException(
0820: "insertTable - table has null-value");
0821: insertTable(aTable, new Point(row, column));
0822: }
0823:
0824: /**
0825: * To put a table within the existing table at the given position
0826: * generateTable will of course re-arrange the widths of the columns.
0827: *
0828: * @param aTable the table you want to insert
0829: * @param aLocation a <CODE>Point</CODE>
0830: */
0831: public void insertTable(Table aTable, Point aLocation) {
0832:
0833: if (aTable == null)
0834: throw new NullPointerException(
0835: "insertTable - table has null-value");
0836: if (aLocation == null)
0837: throw new NullPointerException(
0838: "insertTable - point has null-value");
0839: mTableInserted = true;
0840: aTable.complete();
0841:
0842: if (aLocation.y > columns) {
0843: throw new IllegalArgumentException(
0844: "insertTable -- wrong columnposition("
0845: + aLocation.y + ") of location; max ="
0846: + columns);
0847: }
0848:
0849: int rowCount = aLocation.x + 1 - rows.size();
0850: int i = 0;
0851: if (rowCount > 0) { //create new rows ?
0852: for (; i < rowCount; i++) {
0853: rows.add(new Row(columns));
0854: }
0855: }
0856:
0857: ((Row) rows.get(aLocation.x)).setElement(aTable, aLocation.y);
0858:
0859: setCurrentLocationToNextValidPosition(aLocation);
0860: }
0861:
0862: /**
0863: * Gives you the posibility to add columns.
0864: *
0865: * @param aColumns the number of columns to add
0866: */
0867: public void addColumns(int aColumns) {
0868: ArrayList newRows = new ArrayList(rows.size());
0869:
0870: int newColumns = columns + aColumns;
0871: Row row;
0872: for (int i = 0; i < rows.size(); i++) {
0873: row = new Row(newColumns);
0874: for (int j = 0; j < columns; j++) {
0875: row.setElement(((Row) rows.get(i)).getCell(j), j);
0876: }
0877: for (int j = columns; j < newColumns && i < curPosition.x; j++) {
0878: row.setElement(null, j);
0879: }
0880: newRows.add(row);
0881: }
0882: // applied 1 column-fix; last column needs to have a width of 0
0883: float[] newWidths = new float[newColumns];
0884: System.arraycopy(widths, 0, newWidths, 0, columns);
0885: for (int j = columns; j < newColumns; j++) {
0886: newWidths[j] = 0;
0887: }
0888: columns = newColumns;
0889: widths = newWidths;
0890: rows = newRows;
0891: }
0892:
0893: /**
0894: * Deletes a column in this table.
0895: *
0896: * @param column the number of the column that has to be deleted
0897: * @throws BadElementException
0898: */
0899: public void deleteColumn(int column) throws BadElementException {
0900: float newWidths[] = new float[--columns];
0901: System.arraycopy(widths, 0, newWidths, 0, column);
0902: System.arraycopy(widths, column + 1, newWidths, column, columns
0903: - column);
0904: setWidths(newWidths);
0905: System.arraycopy(widths, 0, newWidths, 0, columns);
0906: widths = newWidths;
0907: Row row;
0908: int size = rows.size();
0909: for (int i = 0; i < size; i++) {
0910: row = (Row) rows.get(i);
0911: row.deleteColumn(column);
0912: rows.set(i, row);
0913: }
0914: if (column == columns) {
0915: curPosition.setLocation(curPosition.x + 1, 0);
0916: }
0917: }
0918:
0919: /**
0920: * Deletes a row.
0921: *
0922: * @param row the number of the row to delete
0923: * @return boolean <CODE>true</CODE> if the row was deleted; <CODE>false</CODE> if not
0924: */
0925: public boolean deleteRow(int row) {
0926: if (row < 0 || row >= rows.size()) {
0927: return false;
0928: }
0929: rows.remove(row);
0930: curPosition.setLocation(curPosition.x - 1, curPosition.y);
0931: return true;
0932: }
0933:
0934: /**
0935: * Deletes all rows in this table.
0936: * (contributed by dperezcar@fcc.es)
0937: */
0938: public void deleteAllRows() {
0939: rows.clear();
0940: rows.add(new Row(columns));
0941: curPosition.setLocation(0, 0);
0942: lastHeaderRow = -1;
0943: }
0944:
0945: /**
0946: * Deletes the last row in this table.
0947: *
0948: * @return boolean <CODE>true</CODE> if the row was deleted; <CODE>false</CODE> if not
0949: */
0950: public boolean deleteLastRow() {
0951: return deleteRow(rows.size() - 1);
0952: }
0953:
0954: /**
0955: * Will fill empty cells with valid blank <CODE>Cell</CODE>s
0956: */
0957: public void complete() {
0958: if (mTableInserted) {
0959: mergeInsertedTables(); // integrate tables in the table
0960: mTableInserted = false;
0961: }
0962: if (autoFillEmptyCells) {
0963: fillEmptyMatrixCells();
0964: }
0965: }
0966:
0967: // private helper classes
0968:
0969: /**
0970: * returns the element at the position row, column
0971: * (Cast to Cell or Table)
0972: *
0973: * @param row
0974: * @param column
0975: * @return dimension
0976: */
0977: private Object getElement(int row, int column) {
0978: return ((Row) rows.get(row)).getCell(column);
0979: }
0980:
0981: /**
0982: * Integrates all added tables and recalculates column widths.
0983: */
0984: private void mergeInsertedTables() {
0985: int i = 0, j = 0;
0986: float[] lNewWidths = null;
0987: int[] lDummyWidths = new int[columns]; // to keep track in how many new cols this one will be split
0988: float[][] lDummyColumnWidths = new float[columns][]; // bugfix Tony Copping
0989: int[] lDummyHeights = new int[rows.size()]; // to keep track in how many new rows this one will be split
0990: ArrayList newRows = null;
0991: boolean isTable = false;
0992: int lTotalRows = 0, lTotalColumns = 0;
0993: int lNewMaxRows = 0, lNewMaxColumns = 0;
0994:
0995: Table lDummyTable = null;
0996:
0997: // first we'll add new columns when needed
0998: // check one column at a time, find maximum needed nr of cols
0999: // Search internal tables and find one with max columns
1000: for (j = 0; j < columns; j++) {
1001: lNewMaxColumns = 1; // value to hold in how many columns the current one will be split
1002: float[] tmpWidths = null;
1003: for (i = 0; i < rows.size(); i++) {
1004: if (Table.class.isInstance(((Row) rows.get(i))
1005: .getCell(j))) {
1006: isTable = true;
1007: lDummyTable = ((Table) ((Row) rows.get(i))
1008: .getCell(j));
1009: if (tmpWidths == null) {
1010: tmpWidths = lDummyTable.widths;
1011: lNewMaxColumns = tmpWidths.length;
1012: } else {
1013: int cols = lDummyTable.getDimension().width;
1014: float[] tmpWidthsN = new float[cols
1015: * tmpWidths.length];
1016: float tpW = 0, btW = 0, totW = 0;
1017: int tpI = 0, btI = 0, totI = 0;
1018: tpW += tmpWidths[0];
1019: btW += lDummyTable.widths[0];
1020: while (tpI < tmpWidths.length && btI < cols) {
1021: if (btW > tpW) {
1022: tmpWidthsN[totI] = tpW - totW;
1023: tpI++;
1024: if (tpI < tmpWidths.length) {
1025: tpW += tmpWidths[tpI];
1026: }
1027: } else {
1028: tmpWidthsN[totI] = btW - totW;
1029: btI++;
1030: if (Math.abs(btW - tpW) < 0.0001) {
1031: tpI++;
1032: if (tpI < tmpWidths.length) {
1033: tpW += tmpWidths[tpI];
1034: }
1035: }
1036: if (btI < cols) {
1037: btW += lDummyTable.widths[btI];
1038: }
1039: }
1040: totW += tmpWidthsN[totI];
1041: totI++;
1042: }
1043: /*if( tpI<tmpWidths.length)
1044: {
1045: System.arraycopy(tmpWidths, tpI, tmpWidthsN, totI, tmpWidths.length-tpI);
1046: totI +=tmpWidths.length-tpI;
1047: }
1048: else if(btI<cols)
1049: {
1050: System.arraycopy(lDummyTable.widths, btI, tmpWidthsN, totI, lDummyTable.widths.length-btI);
1051: totI +=lDummyTable.widths.length-btI; }*/
1052: tmpWidths = new float[totI];
1053: System.arraycopy(tmpWidthsN, 0, tmpWidths, 0,
1054: totI);
1055: lNewMaxColumns = totI;
1056: }
1057: /*if ( lDummyTable.getDimension().width > lNewMaxColumns )
1058: {
1059: lNewMaxColumns = lDummyTable.getDimension().width;
1060: lDummyColumnWidths[j] = lDummyTable.widths; // bugfix Tony Copping
1061: }*/
1062: }
1063: }
1064: lDummyColumnWidths[j] = tmpWidths;
1065: lTotalColumns += lNewMaxColumns;
1066: lDummyWidths[j] = lNewMaxColumns;
1067: }
1068:
1069: // next we'll add new rows when needed
1070: for (i = 0; i < rows.size(); i++) {
1071: lNewMaxRows = 1; // holds value in how many rows the current one will be split
1072: for (j = 0; j < columns; j++) {
1073: if (Table.class.isInstance(((Row) rows.get(i))
1074: .getCell(j))) {
1075: isTable = true;
1076: lDummyTable = (Table) ((Row) rows.get(i))
1077: .getCell(j);
1078: if (lDummyTable.getDimension().height > lNewMaxRows) {
1079: lNewMaxRows = lDummyTable.getDimension().height;
1080: }
1081: }
1082: }
1083: lTotalRows += lNewMaxRows;
1084: lDummyHeights[i] = lNewMaxRows;
1085: }
1086:
1087: if ((lTotalColumns != columns) || (lTotalRows != rows.size())
1088: || isTable) // NO ADJUSTMENT
1089: {
1090: // ** WIDTH
1091: // set correct width for new columns
1092: // divide width over new nr of columns
1093: // Take new max columns of internal table and work out widths for each col
1094: lNewWidths = new float[lTotalColumns];
1095: int lDummy = 0;
1096: for (int tel = 0; tel < widths.length; tel++) {
1097: if (lDummyWidths[tel] != 1) {
1098: // divide
1099: for (int tel2 = 0; tel2 < lDummyWidths[tel]; tel2++) {
1100: // lNewWidths[lDummy] = widths[tel] / lDummyWidths[tel];
1101: lNewWidths[lDummy] = widths[tel]
1102: * lDummyColumnWidths[tel][tel2] / 100f; // bugfix Tony Copping
1103: lDummy++;
1104: }
1105: } else {
1106: lNewWidths[lDummy] = widths[tel];
1107: lDummy++;
1108: }
1109: }
1110:
1111: // ** FILL OUR NEW TABLE
1112: // generate new table
1113: // set new widths
1114: // copy old values
1115: newRows = new ArrayList(lTotalRows);
1116: for (i = 0; i < lTotalRows; i++) {
1117: newRows.add(new Row(lTotalColumns));
1118: }
1119: int lDummyRow = 0, lDummyColumn = 0; // to remember where we are in the new, larger table
1120: Object lDummyElement = null;
1121: for (i = 0; i < rows.size(); i++) {
1122: lDummyColumn = 0;
1123: lNewMaxRows = 1;
1124: for (j = 0; j < columns; j++) {
1125: if (Table.class.isInstance(((Row) rows.get(i))
1126: .getCell(j))) // copy values from embedded table
1127: {
1128: lDummyTable = (Table) ((Row) rows.get(i))
1129: .getCell(j);
1130:
1131: // Work out where columns in table table correspond to columns in current table
1132: int colMap[] = new int[lDummyTable.widths.length + 1];
1133: int cb = 0, ct = 0;
1134:
1135: for (; cb < lDummyTable.widths.length; cb++) {
1136: colMap[cb] = lDummyColumn + ct;
1137:
1138: float wb;
1139: wb = lDummyTable.widths[cb];
1140:
1141: float wt = 0;
1142: while (ct < lDummyWidths[j]) {
1143: wt += lDummyColumnWidths[j][ct++];
1144: if (Math.abs(wb - wt) < 0.0001)
1145: break;
1146: }
1147: }
1148: colMap[cb] = lDummyColumn + ct;
1149:
1150: // need to change this to work out how many cols to span
1151: for (int k = 0; k < lDummyTable.getDimension().height; k++) {
1152: for (int l = 0; l < lDummyTable
1153: .getDimension().width; l++) {
1154: lDummyElement = lDummyTable.getElement(
1155: k, l);
1156: if (lDummyElement != null) {
1157: int col = lDummyColumn + l;
1158:
1159: if (Cell.class
1160: .isInstance(lDummyElement)) {
1161: Cell lDummyC = (Cell) lDummyElement;
1162: // Find col to add cell in and set col span
1163: col = colMap[l];
1164: int ot = colMap[l
1165: + lDummyC.getColspan()];
1166:
1167: lDummyC.setColspan(ot - col);
1168: }
1169:
1170: ((Row) newRows.get(k + lDummyRow))
1171: .addElement(lDummyElement,
1172: col); // use addElement to set reserved status ok in row
1173: }
1174: }
1175: }
1176: } else // copy others values
1177: {
1178: Object aElement = getElement(i, j);
1179:
1180: if (Cell.class.isInstance(aElement)) {
1181:
1182: // adjust spans for cell
1183: ((Cell) aElement)
1184: .setRowspan(((Cell) ((Row) rows
1185: .get(i)).getCell(j))
1186: .getRowspan()
1187: + lDummyHeights[i] - 1);
1188: ((Cell) aElement)
1189: .setColspan(((Cell) ((Row) rows
1190: .get(i)).getCell(j))
1191: .getColspan()
1192: + lDummyWidths[j] - 1);
1193:
1194: // most likely this cell covers a larger area because of the row/cols splits : define not-to-be-filled cells
1195: placeCell(newRows, ((Cell) aElement),
1196: new Point(lDummyRow, lDummyColumn));
1197: }
1198: }
1199: lDummyColumn += lDummyWidths[j];
1200: }
1201: lDummyRow += lDummyHeights[i];
1202: }
1203:
1204: // Set our new matrix
1205: columns = lTotalColumns;
1206: rows = newRows;
1207: this .widths = lNewWidths;
1208: }
1209: }
1210:
1211: /**
1212: * adds new<CODE>Cell</CODE>'s to empty/null spaces.
1213: */
1214: private void fillEmptyMatrixCells() {
1215: try {
1216: for (int i = 0; i < rows.size(); i++) {
1217: for (int j = 0; j < columns; j++) {
1218: if (!((Row) rows.get(i)).isReserved(j)) {
1219: addCell(defaultLayout, new Point(i, j));
1220: }
1221: }
1222: }
1223: } catch (BadElementException bee) {
1224: throw new ExceptionConverter(bee);
1225: }
1226: }
1227:
1228: /**
1229: * check if <CODE>Cell</CODE> 'fits' the table.
1230: * <P>
1231: * <UL><LI>rowspan/colspan not beyond borders
1232: * <LI>spanned cell don't overlap existing cells</UL>
1233: *
1234: * @param aCell the cell that has to be checked
1235: * @param aLocation the location where the cell has to be placed
1236: * @return true if the location was valid
1237: */
1238: private boolean isValidLocation(Cell aCell, Point aLocation) {
1239: // rowspan not beyond last column
1240: if (aLocation.x < rows.size()) // if false : new location is already at new, not-yet-created area so no check
1241: {
1242: if ((aLocation.y + aCell.getColspan()) > columns) {
1243: return false;
1244: }
1245:
1246: int difx = ((rows.size() - aLocation.x) > aCell
1247: .getRowspan()) ? aCell.getRowspan() : rows.size()
1248: - aLocation.x;
1249: int dify = ((columns - aLocation.y) > aCell.getColspan()) ? aCell
1250: .getColspan()
1251: : columns - aLocation.y;
1252: // no other content at cells targetted by rowspan/colspan
1253: for (int i = aLocation.x; i < (aLocation.x + difx); i++) {
1254: for (int j = aLocation.y; j < (aLocation.y + dify); j++) {
1255: if (((Row) rows.get(i)).isReserved(j)) {
1256: return false;
1257: }
1258: }
1259: }
1260: } else {
1261: if ((aLocation.y + aCell.getColspan()) > columns) {
1262: return false;
1263: }
1264: }
1265:
1266: return true;
1267: }
1268:
1269: /**
1270: * Sets the unset cell properties to be the table defaults.
1271: *
1272: * @param aCell The cell to set to table defaults as necessary.
1273: */
1274: private void assumeTableDefaults(Cell aCell) {
1275:
1276: if (aCell.getBorder() == Rectangle.UNDEFINED) {
1277: aCell.setBorder(defaultLayout.getBorder());
1278: }
1279: if (aCell.getBorderWidth() == Rectangle.UNDEFINED) {
1280: aCell.setBorderWidth(defaultLayout.getBorderWidth());
1281: }
1282: if (aCell.getBorderColor() == null) {
1283: aCell.setBorderColor(defaultLayout.getBorderColor());
1284: }
1285: if (aCell.getBackgroundColor() == null) {
1286: aCell
1287: .setBackgroundColor(defaultLayout
1288: .getBackgroundColor());
1289: }
1290: if (aCell.getHorizontalAlignment() == Element.ALIGN_UNDEFINED) {
1291: aCell.setHorizontalAlignment(defaultLayout
1292: .getHorizontalAlignment());
1293: }
1294: if (aCell.getVerticalAlignment() == Element.ALIGN_UNDEFINED) {
1295: aCell.setVerticalAlignment(defaultLayout
1296: .getVerticalAlignment());
1297: }
1298: }
1299:
1300: /**
1301: * Inserts a Cell in a cell-array and reserves cells defined by row-/colspan.
1302: *
1303: * @param someRows some rows
1304: * @param aCell the cell that has to be inserted
1305: * @param aPosition the position where the cell has to be placed
1306: */
1307: private void placeCell(ArrayList someRows, Cell aCell,
1308: Point aPosition) {
1309: int i;
1310: Row row = null;
1311: int rowCount = aPosition.x + aCell.getRowspan()
1312: - someRows.size();
1313: assumeTableDefaults(aCell);
1314: if ((aPosition.x + aCell.getRowspan()) > someRows.size()) {
1315: for (i = 0; i < rowCount; i++) {
1316: row = new Row(columns);
1317: someRows.add(row);
1318: }
1319: }
1320:
1321: // reserve cell in rows below
1322: for (i = aPosition.x + 1; i < (aPosition.x + aCell.getRowspan()); i++) {
1323: if (!((Row) someRows.get(i)).reserve(aPosition.y, aCell
1324: .getColspan())) {
1325:
1326: // should be impossible to come here :-)
1327: throw new RuntimeException("addCell - error in reserve");
1328: }
1329: }
1330: row = (Row) someRows.get(aPosition.x);
1331: row.addElement(aCell, aPosition.y);
1332:
1333: }
1334:
1335: /**
1336: * Sets current col/row to valid(empty) pos after addCell/Table
1337: * @param aLocation a location in the Table
1338: */
1339: private void setCurrentLocationToNextValidPosition(Point aLocation) {
1340: // set latest location to next valid position
1341: int i, j;
1342: i = aLocation.x;
1343: j = aLocation.y;
1344: do {
1345: if ((j + 1) == columns) { // goto next row
1346: i++;
1347: j = 0;
1348: } else {
1349: j++;
1350: }
1351: } while ((i < rows.size()) && (j < columns)
1352: && (((Row) rows.get(i)).isReserved(j)));
1353: curPosition = new Point(i, j);
1354: }
1355:
1356: // public helper methods
1357:
1358: /**
1359: * Gets an array with the positions of the borders between every column.
1360: * <P>
1361: * This method translates the widths expressed in percentages into the
1362: * x-coordinate of the borders of the columns on a real document.
1363: *
1364: * @param left this is the position of the first border at the left (cellpadding not included)
1365: * @param totalWidth this is the space between the first border at the left
1366: * and the last border at the right (cellpadding not included)
1367: * @return an array with borderpositions
1368: */
1369: public float[] getWidths(float left, float totalWidth) {
1370: // for x columns, there are x+1 borders
1371: float[] w = new float[columns + 1];
1372: float wPercentage;
1373: if (locked) {
1374: wPercentage = 100 * width / totalWidth;
1375: } else {
1376: wPercentage = width;
1377: }
1378: // the border at the left is calculated
1379: switch (alignment) {
1380: case Element.ALIGN_LEFT:
1381: w[0] = left;
1382: break;
1383: case Element.ALIGN_RIGHT:
1384: w[0] = left + (totalWidth * (100 - wPercentage)) / 100;
1385: break;
1386: case Element.ALIGN_CENTER:
1387: default:
1388: w[0] = left + (totalWidth * (100 - wPercentage)) / 200;
1389: }
1390: // the total available width is changed
1391: totalWidth = (totalWidth * wPercentage) / 100;
1392: // the inner borders are calculated
1393: for (int i = 1; i < columns; i++) {
1394: w[i] = w[i - 1] + (widths[i - 1] * totalWidth / 100);
1395: }
1396: // the border at the right is calculated
1397: w[columns] = w[0] + totalWidth;
1398: return w;
1399: }
1400:
1401: /**
1402: * Gets an <CODE>Iterator</CODE> of all the <CODE>Row</CODE>s.
1403: *
1404: * @return an <CODE>Iterator</CODE>
1405: */
1406: public Iterator iterator() {
1407: return rows.iterator();
1408: }
1409:
1410: /**
1411: * Create a PdfPTable based on this Table object.
1412: * @return a PdfPTable object
1413: * @throws BadElementException
1414: */
1415: public PdfPTable createPdfPTable() throws BadElementException {
1416: if (!convert2pdfptable) {
1417: throw new BadElementException(
1418: "No error, just an old style table");
1419: }
1420: setAutoFillEmptyCells(true);
1421: complete();
1422: PdfPTable pdfptable = new PdfPTable(widths);
1423: pdfptable.setTableEvent(SimpleTable.getDimensionlessInstance(
1424: this , cellspacing));
1425: pdfptable.setHeaderRows(lastHeaderRow + 1);
1426: pdfptable.setSplitLate(cellsFitPage);
1427: pdfptable.setKeepTogether(tableFitsPage);
1428: if (!Float.isNaN(offset)) {
1429: pdfptable.setSpacingBefore(offset);
1430: }
1431: pdfptable.setHorizontalAlignment(alignment);
1432: if (locked) {
1433: pdfptable.setTotalWidth(width);
1434: pdfptable.setLockedWidth(true);
1435: } else {
1436: pdfptable.setWidthPercentage(width);
1437: }
1438: Row row;
1439: for (Iterator iterator = iterator(); iterator.hasNext();) {
1440: row = (Row) iterator.next();
1441: Element cell;
1442: PdfPCell pcell;
1443: for (int i = 0; i < row.getColumns(); i++) {
1444: if ((cell = (Element) row.getCell(i)) != null) {
1445: if (cell instanceof Table) {
1446: pcell = new PdfPCell(((Table) cell)
1447: .createPdfPTable());
1448: } else if (cell instanceof Cell) {
1449: pcell = ((Cell) cell).createPdfPCell();
1450: pcell
1451: .setPadding(cellpadding + cellspacing
1452: / 2f);
1453: pcell.setCellEvent(SimpleCell
1454: .getDimensionlessInstance((Cell) cell,
1455: cellspacing));
1456: } else {
1457: pcell = new PdfPCell();
1458: }
1459: pdfptable.addCell(pcell);
1460: }
1461: }
1462: }
1463: return pdfptable;
1464: }
1465:
1466: // deprecated stuff
1467:
1468: /**
1469: * Returns a <CODE>Table</CODE> that has been constructed taking in account
1470: * the value of some <VAR>attributes</VAR>.
1471: *
1472: * @param attributes Some attributes
1473: * @throws BadElementException
1474: * @deprecated
1475: */
1476: public Table(java.util.Properties attributes) {
1477: this (com.lowagie.text.factories.ElementFactory
1478: .getTable(attributes));
1479: }
1480:
1481: /**
1482: * Gets the number of columns.
1483: *
1484: * @return a value
1485: * @deprecated Use {@link #getColumns()} instead
1486: */
1487: public int columns() {
1488: return getColumns();
1489: }
1490:
1491: /**
1492: * Gets the horizontal alignment.
1493: *
1494: * @return a value
1495: * @deprecated Use {@link #getAlignment()} instead
1496: */
1497: public int alignment() {
1498: return getAlignment();
1499: }
1500:
1501: /**
1502: * Gets the cellpadding.
1503: *
1504: * @return a value
1505: * @deprecated Use {@link #getPadding()} instead
1506: */
1507: public float cellpadding() {
1508: return getPadding();
1509: }
1510:
1511: /**
1512: * Gets the cellspacing.
1513: *
1514: * @return a value
1515: * @deprecated Use {@link #getSpacing()} instead
1516: */
1517: public float cellspacing() {
1518: return getSpacing();
1519: }
1520:
1521: /**
1522: * Sets the cellpadding.
1523: *
1524: * @param value the new value
1525: * @deprecated use setPadding
1526: */
1527: public void setSpaceInsideCell(float value) {
1528: cellpadding = value;
1529: }
1530:
1531: /**
1532: * Sets the cellspacing.
1533: *
1534: * @param value the new value
1535: * @deprecated use setSpacing
1536: */
1537: public void setSpaceBetweenCells(float value) {
1538: cellspacing = value;
1539: }
1540:
1541: /**
1542: * Gets the last number of the rows that contain headers.
1543: *
1544: * @return a rownumber
1545: * @deprecated Use {@link #getLastHeaderRow()} instead
1546: */
1547: public int lastHeaderRow() {
1548: return getLastHeaderRow();
1549: }
1550:
1551: /**
1552: * Gets the table width (a percentage).
1553: *
1554: * @return the table width
1555: * @deprecated Use {@link #getWidth()} instead
1556: */
1557: public float widthPercentage() {
1558: return getWidth();
1559: }
1560:
1561: /**
1562: * Sets the width of this table (in percentage of the available space).
1563: *
1564: * @param width the width
1565: * @deprecated setTotalWidth(int width)
1566: */
1567: public void setAbsWidth(String width) {
1568: setWidth(Float.parseFloat(width + "f"));
1569: setLocked(true);
1570: }
1571:
1572: /**
1573: * Gets the table width (in pixels).
1574: *
1575: * @return the table width
1576: * @deprecated use getWidth
1577: */
1578: public String absWidth() {
1579: if (isLocked())
1580: return String.valueOf(width);
1581: else
1582: return "";
1583: }
1584:
1585: // setters for default cell
1586:
1587: /**
1588: * Changes the border in the default layout of the <CODE>Cell</CODE>s
1589: * added with method <CODE>addCell(String content)</CODE>.
1590: *
1591: * @param value the new border value
1592: * @deprecated use getDefaultCell.setBorder
1593: */
1594: public void setDefaultCellBorder(int value) {
1595: defaultLayout.setBorder(value);
1596: }
1597:
1598: /**
1599: * Changes the width of the borders in the default layout of the <CODE>Cell</CODE>s
1600: * added with method <CODE>addCell(String content)</CODE>.
1601: *
1602: * @param value the new width
1603: * @deprecated use getDefaultCell.setBorderWidth
1604: */
1605: public void setDefaultCellBorderWidth(float value) {
1606: defaultLayout.setBorderWidth(value);
1607: }
1608:
1609: /**
1610: * Changes the bordercolor in the default layout of the <CODE>Cell</CODE>s
1611: * added with method <CODE>addCell(String content)</CODE>.
1612: *
1613: * @param color the new color
1614: * @deprecated getDefaultCell.setBorderColor
1615: */
1616: public void setDefaultCellBorderColor(Color color) {
1617: defaultLayout.setBorderColor(color);
1618: }
1619:
1620: /**
1621: * Changes the backgroundcolor in the default layout of the <CODE>Cell</CODE>s
1622: * added with method <CODE>addCell(String content)</CODE>.
1623: *
1624: * @param color the new color
1625: * @deprecated use getDefaultCell.setBackgroundColor
1626: */
1627: public void setDefaultCellBackgroundColor(Color color) {
1628: defaultLayout.setBackgroundColor(color);
1629: }
1630:
1631: /**
1632: * Changes the grayfill in the default layout of the <CODE>Cell</CODE>s
1633: * added with method <CODE>addCell(String content)</CODE>.
1634: *
1635: * @param value the new value
1636: * @deprecated use getDefaultCell.setGrayFill
1637: */
1638: public void setDefaultCellGrayFill(float value) {
1639: if (value >= 0 && value <= 1) {
1640: defaultLayout.setGrayFill(value);
1641: }
1642: }
1643:
1644: /**
1645: * Changes the horizontalAlignment in the default layout of the <CODE>Cell</CODE>s
1646: * added with method <CODE>addCell(String content)</CODE>.
1647: *
1648: * @param value the new alignment value
1649: * @deprecated use getDefaultCell.setHorizontalAlignment
1650: */
1651: public void setDefaultHorizontalAlignment(int value) {
1652: defaultLayout.setHorizontalAlignment(value);
1653: }
1654:
1655: /**
1656: * Changes the verticalAlignment in the default layout of the <CODE>Cell</CODE>s
1657: * added with method <CODE>addCell(String content)</CODE>.
1658: *
1659: * @param value the new alignment value
1660: * @deprecated use getDefaultCell.setVerticalAlignment
1661: */
1662: public void setDefaultVerticalAlignment(int value) {
1663: defaultLayout.setVerticalAlignment(value);
1664: }
1665:
1666: /**
1667: * Changes the rowspan in the default layout of the <CODE>Cell</CODE>s
1668: * added with method <CODE>addCell(String content)</CODE>.
1669: *
1670: * @param value the new rowspan value
1671: * @deprecated use getDefaultCell.setRowspan
1672: */
1673: public void setDefaultRowspan(int value) {
1674: defaultLayout.setRowspan(value);
1675: }
1676:
1677: /**
1678: * Changes the colspan in the default layout of the <CODE>Cell</CODE>s
1679: * added with method <CODE>addCell(String content)</CODE>.
1680: *
1681: * @param value the new colspan value
1682: * @deprecated use getDefaultCell.setColspan
1683: */
1684: public void setDefaultColspan(int value) {
1685: defaultLayout.setColspan(value);
1686: }
1687:
1688: }
|