KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > Table


1 /*
2  * $Id: Table.java 2766 2007-05-20 11:40:29Z blowagie $
3  * $Name$
4  *
5  * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
6  *
7  * The contents of this file are subject to the Mozilla Public License Version 1.1
8  * (the "License"); you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the License.
14  *
15  * The Original Code is 'iText, a free JAVA-PDF library'.
16  *
17  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
18  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
19  * All Rights Reserved.
20  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
21  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
22  *
23  * Contributor(s): all the names of the contributors are added in the source code
24  * where applicable.
25  *
26  * Alternatively, the contents of this file may be used under the terms of the
27  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
28  * provisions of LGPL are applicable instead of those above. If you wish to
29  * allow use of your version of this file only under the terms of the LGPL
30  * License and not to allow others to use your version of this file under
31  * the MPL, indicate your decision by deleting the provisions above and
32  * replace them with the notice and other provisions required by the LGPL.
33  * If you do not delete the provisions above, a recipient may use your version
34  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE
35  *
36  * This library is free software; you can redistribute it and/or modify it
37  * under the terms of the MPL as stated above or under the terms of the GNU
38  * Library General Public License as published by the Free Software Foundation;
39  * either version 2 of the License, or any later version.
40  *
41  * This library is distributed in the hope that it will be useful, but WITHOUT
42  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
43  * FOR A PARTICULAR PURPOSE. See the GNU LIBRARY GENERAL PUBLIC LICENSE for more
44  * details.
45  *
46  * If you didn't download this code from the following link, you should check if
47  * you aren't using an obsolete version:
48  * http://www.lowagie.com/iText/
49  *
50  * Some methods in this class were contributed by Geert Poels, Kris Jespers and
51  * Steve Ogryzek. Check the CVS repository.
52  */

53
54 package com.lowagie.text;
55
56 import java.awt.Color JavaDoc;
57 import java.awt.Dimension JavaDoc;
58 import java.awt.Point JavaDoc;
59 import java.util.ArrayList JavaDoc;
60 import java.util.Iterator JavaDoc;
61
62 import com.lowagie.text.pdf.PdfPCell;
63 import com.lowagie.text.pdf.PdfPTable;
64
65 /**
66  * A <CODE>Table</CODE> is a <CODE>Rectangle</CODE> that contains <CODE>Cell</CODE>s,
67  * ordered in some kind of matrix.
68  * <P>
69  * Tables that span multiple pages are cut into different parts automatically.
70  * If you want a table header to be repeated on every page, you may not forget to
71  * mark the end of the header section by using the method <CODE>endHeaders()</CODE>.
72  * <P>
73  * The matrix of a table is not necessarily an m x n-matrix. It can contain holes
74  * or cells that are bigger than the unit. Believe me or not, but it took some serious
75  * thinking to make this as userfriendly as possible. I hope you wil find the result
76  * quite simple (I love simple solutions, especially for complex problems).
77  * I didn't want it to be something as complex as the Java <CODE>GridBagLayout</CODE>.
78  * <P>
79  * Example:
80  * <BLOCKQUOTE><PRE>
81  * // Remark: You MUST know the number of columns when constructing a Table.
82  * // The number of rows is not important.
83  * <STRONG>Table table = new Table(3);</STRONG>
84  * <STRONG>table.setBorderWidth(1);</STRONG>
85  * <STRONG>table.setBorderColor(new Color(0, 0, 255));</STRONG>
86  * <STRONG>table.setPadding(5);</STRONG>
87  * <STRONG>table.setSpacing(5);</STRONG>
88  * Cell cell = new Cell("header");
89  * cell.setHeader(true);
90  * cell.setColspan(3);
91  * <STRONG>table.addCell(cell);</STRONG>
92  * <STRONG>table.endHeaders();</STRONG>
93  * cell = new Cell("example cell with colspan 1 and rowspan 2");
94  * cell.setRowspan(2);
95  * cell.setBorderColor(new Color(255, 0, 0));
96  * <STRONG>table.addCell(cell);</STRONG>
97  * <STRONG>table.addCell("1.1");</STRONG>
98  * <STRONG>table.addCell("2.1");</STRONG>
99  * <STRONG>table.addCell("1.2");</STRONG>
100  * <STRONG>table.addCell("2.2");</STRONG>
101  * <STRONG>table.addCell("cell test1");</STRONG>
102  * cell = new Cell("big cell");
103  * cell.setRowspan(2);
104  * cell.setColspan(2);
105  * <STRONG>table.addCell(cell);</STRONG>
106  * <STRONG>table.addCell("cell test2");</STRONG>
107  * </PRE></BLOCKQUOTE>
108  * The result of this code is a table:
109  * <TABLE ALIGN="Center" BORDER="1" BORDERCOLOR="#0000ff" CELLPADDING="5" CELLSPACING="5">
110  * <TR ALIGN="Left" VALIGN="Left">
111  * <TH ALIGN="Left" COLSPAN="3" VALIGN="Left">
112  * header
113  * </TH>
114  * </TR>
115  * <TR ALIGN="Left" VALIGN="Left">
116  * <TD ALIGN="Left" BORDERCOLOR="#ff0000" ROWSPAN="2" VALIGN="Left">
117  * example cell with colspan 1 and rowspan 2
118  * </TD>
119  * <TD ALIGN="Left" VALIGN="Left">
120  * 1.1
121  * </TD>
122  * <TD ALIGN="Left" VALIGN="Left">
123  * 2.1
124  * </TD>
125  * </TR>
126  * <TR ALIGN="Left" VALIGN="Left">
127  * <TD ALIGN="Left" VALIGN="Left">
128  * 1.2
129  * </TD>
130  * <TD ALIGN="Left" VALIGN="Left">
131  * 2.2
132  * </TD>
133  * </TR>
134  * <TR ALIGN="Left" VALIGN="Left">
135  * <TD ALIGN="Left" VALIGN="Left">
136  * cell test1
137  * </TD>
138  * <TD ALIGN="Left" COLSPAN="2" ROWSPAN="2" VALIGN="Left">
139  * big cell
140  * </TD>
141  * </TR>
142  * <TR ALIGN="Left" VALIGN="Left">
143  * <TD ALIGN="Left" VALIGN="Left">
144  * cell test2
145  * </TD>
146  * </TR>
147  * </TABLE>
148  *
149  * @see Rectangle
150  * @see Element
151  * @see Row
152  * @see Cell
153  */

154
155 public class Table extends Rectangle {
156     
157     // membervariables
158

159     /** This is the number of columns in the <CODE>Table</CODE>. */
160     private int columns;
161     
162     /** This is the list of <CODE>Row</CODE>s. */
163     private ArrayList JavaDoc rows = new ArrayList JavaDoc();
164     
165     /** The current Position in the table. */
166     private Point JavaDoc curPosition = new Point JavaDoc(0, 0);
167     
168     /** This Empty Cell contains the DEFAULT layout of each Cell added with the method addCell(String content). */
169     private Cell defaultLayout = new Cell(true);
170     
171     /** This is the number of the last row of the table headers. */
172     private int lastHeaderRow = -1;
173     
174     /** This is the horizontal alignment. */
175     private int alignment = Element.ALIGN_CENTER;
176     
177     /** This is cellpadding. */
178     private float cellpadding;
179     
180     /** This is cellspacing. */
181     private float cellspacing;
182     
183     /** This is the width of the table (in percent of the available space). */
184     private float width = 80;
185     
186     /** Is the width a percentage (false) or an absolute width (true)? */
187     private boolean locked = false;
188     
189     /** This is an array containing the widths (in percentages) of every column. */
190     private float[] widths;
191     
192     /** Boolean to track if a table was inserted (to avoid unnecessary computations afterwards) */
193     private boolean mTableInserted = false;
194     
195     /**
196      * Boolean to automatically fill empty cells before a table is rendered
197      * (takes CPU so may be set to false in case of certainty)
198      */

199     protected boolean autoFillEmptyCells = false;
200     
201     /** If true this table may not be split over two pages. */
202     boolean tableFitsPage = false;
203     
204     /** If true cells may not be split over two pages. */
205     boolean cellsFitPage = false;
206     
207     /** This is the offset of the table. */
208     float offset = Float.NaN;
209     
210     /** if you want to generate tables the old way, set this value to false. */
211     protected boolean convert2pdfptable = false;
212     
213     // constructors
214

215     /**
216      * Constructs a <CODE>Table</CODE> with a certain number of columns.
217      *
218      * @param columns The number of columns in the table
219      * @throws BadElementException if the creator was called with less than 1 column
220      */

221     public Table(int columns) throws BadElementException {
222         this(columns, 1);
223     }
224     
225     /**
226      * Constructs a <CODE>Table</CODE> with a certain number of columns
227      * and a certain number of <CODE>Row</CODE>s.
228      *
229      * @param columns The number of columns in the table
230      * @param rows The number of rows
231      * @throws BadElementException if the creator was called with less than 1 column
232      */

233     public Table(int columns, int rows) throws BadElementException {
234         // a Rectangle is create with BY DEFAULT a border with a width of 1
235
super(0, 0, 0, 0);
236         setBorder(BOX);
237         setBorderWidth(1);
238         defaultLayout.setBorder(BOX);
239         
240         // a table should have at least 1 column
241
if (columns <= 0) {
242             throw new BadElementException("A table should have at least 1 column.");
243         }
244         this.columns = columns;
245         
246         // a certain number of rows are created
247
for (int i = 0; i < rows; i++) {
248             this.rows.add(new Row(columns));
249         }
250         curPosition = new Point JavaDoc(0, 0);
251         
252         // the DEFAULT widths are calculated
253
widths = new float[columns];
254         float width = 100f / columns;
255         for (int i = 0; i < columns; i++) {
256             widths[i] = width;
257         }
258     }
259     
260     /**
261      * Copy constructor (shallow copy).
262      * @throws BadElementException
263      */

264     public Table(Table t) {
265         super(0, 0, 0, 0);
266         this.cloneNonPositionParameters(t);
267         this.columns = t.columns;
268         this.rows = t.rows;
269         this.curPosition = t.curPosition;
270         this.defaultLayout = t.defaultLayout;
271         this.lastHeaderRow = t.lastHeaderRow;
272         this.alignment = t.alignment;
273         this.cellpadding = t.cellpadding;
274         this.cellspacing = t.cellspacing;
275         this.width = t.width;
276         this.widths = t.widths;
277         this.autoFillEmptyCells = t.autoFillEmptyCells;
278         this.tableFitsPage = t.tableFitsPage;
279         this.cellsFitPage = t.cellsFitPage;
280         this.offset = t.offset;
281         this.convert2pdfptable = t.convert2pdfptable;
282     }
283     
284     // implementation of the Element-methods
285

286     /**
287      * Processes the element by adding it (or the different parts) to an
288      * <CODE>ElementListener</CODE>.
289      *
290      * @param listener an <CODE>ElementListener</CODE>
291      * @return <CODE>true</CODE> if the element was processed successfully
292      */

293     public boolean process(ElementListener listener) {
294         try {
295             return listener.add(this);
296         }
297         catch(DocumentException de) {
298             return false;
299         }
300     }
301     
302     /**
303      * Gets the type of the text element.
304      *
305      * @return a type
306      */

307     public int type() {
308         return Element.TABLE;
309     }
310     
311     /**
312      * Gets all the chunks in this element.
313      *
314      * @return an <CODE>ArrayList</CODE>
315      */

316     
317     public ArrayList JavaDoc getChunks() {
318         return new ArrayList JavaDoc();
319     }
320     
321     // getters and setters
322

323     /**
324      * Gets the number of columns.
325      *
326      * @return a value
327      */

328     public int getColumns() {
329         return columns;
330     }
331     
332     /**
333      * Gets the number of rows in this <CODE>Table</CODE>.
334      *
335      * @return the number of rows in this <CODE>Table</CODE>
336      */

337     public int size() {
338         return rows.size();
339     }
340     
341     /**
342      * Gets the dimension of this table
343      *
344      * @return dimension
345      */

346     public Dimension JavaDoc getDimension() {
347         return new Dimension JavaDoc(columns, size());
348     }
349     
350     /**
351      * Gets the default layout of the Table.
352      * @return a cell with all the defaults
353      */

354     public Cell getDefaultLayout() {
355         return defaultLayout;
356     }
357     
358     /**
359      * Sets the default layout of the Table to
360      * the provided Cell
361      * @param value a cell with all the defaults
362      */

363     public void setDefaultLayout(Cell value) {
364         defaultLayout = value;
365     }
366
367     /**
368      * Gets the last number of the rows that contain headers.
369      *
370      * @return a rownumber
371      */

372     public int getLastHeaderRow() {
373         return this.lastHeaderRow;
374     }
375     
376     /**
377      * Sets the horizontal alignment.
378      *
379      * @param value the new value
380      */

381     public void setLastHeaderRow(int value) {
382         lastHeaderRow = value;
383     }
384     
385     /**
386      * Marks the last row of the table headers.
387      *
388      * @return the number of the last row of the table headers
389      */

390     public int endHeaders() {
391         lastHeaderRow = curPosition.x - 1;
392         return lastHeaderRow;
393     }
394
395     /**
396      * Gets the horizontal alignment.
397      *
398      * @return a value
399      */

400     public int getAlignment() {
401         return alignment;
402     }
403     
404     /**
405      * Sets the horizontal alignment.
406      *
407      * @param value the new value
408      */

409     public void setAlignment(int value) {
410         alignment = value;
411     }
412     
413     /**
414      * Sets the alignment of this paragraph.
415      *
416      * @param alignment the new alignment as a <CODE>String</CODE>
417      */

418     public void setAlignment(String JavaDoc alignment) {
419         if (ElementTags.ALIGN_LEFT.equalsIgnoreCase(alignment)) {
420             this.alignment = Element.ALIGN_LEFT;
421             return;
422         }
423         if (ElementTags.RIGHT.equalsIgnoreCase(alignment)) {
424             this.alignment = Element.ALIGN_RIGHT;
425             return;
426         }
427         this.alignment = Element.ALIGN_CENTER;
428     }
429
430     /**
431      * Gets the cellpadding.
432      *
433      * @return a value
434      */

435     public float getPadding() {
436         return cellpadding;
437     }
438     
439     /**
440      * Sets the cellpadding.
441      *
442      * @param value the new value
443      */

444     public void setPadding(float value) {
445         cellpadding = value;
446     }
447
448     /**
449      * Gets the cellspacing.
450      *
451      * @return a value
452      */

453     public float getSpacing() {
454         return cellspacing;
455     }
456     
457     /**
458      * Sets the cellspacing.
459      *
460      * @param value the new value
461      */

462     public void setSpacing(float value) {
463         cellspacing = value;
464     }
465     
466     /**
467      * Enables/disables automatic insertion of empty cells before table is rendered. (default = false)
468      * As some people may want to create a table, fill only a couple of the cells and don't bother with
469      * investigating which empty ones need to be added, this default behaviour may be very welcome.
470      * Disabling is recommended to increase speed. (empty cells should be added through extra code then)
471      *
472      * @param aDoAutoFill enable/disable autofill
473      */

474     public void setAutoFillEmptyCells(boolean aDoAutoFill) {
475         autoFillEmptyCells = aDoAutoFill;
476     }
477
478     /**
479      * Gets the table width (a percentage).
480      *
481      * @return the table width
482      */

483     public float getWidth() {
484         return width;
485     }
486     
487     /**
488      * Sets the width of this table (in percentage of the available space).
489      *
490      * @param width the width
491      */

492     public void setWidth(float width) {
493         this.width = width;
494     }
495     
496     /**
497      * @return the locked
498      */

499     public boolean isLocked() {
500         return locked;
501     }
502
503     /**
504      * @param locked the locked to set
505      */

506     public void setLocked(boolean locked) {
507         this.locked = locked;
508     }
509
510     /**
511      * Gets the proportional widths of the columns in this <CODE>Table</CODE>.
512      *
513      * @return the proportional widths of the columns in this <CODE>Table</CODE>
514      */

515     public float[] getProportionalWidths() {
516         return widths;
517     }
518     
519     /**
520      * Sets the widths of the different columns (percentages).
521      * <P>
522      * You can give up relative values of borderwidths.
523      * The sum of these values will be considered 100%.
524      * The values will be recalculated as percentages of this sum.
525      * <P>
526      * example:
527      * <BLOCKQUOTE><PRE>
528      * float[] widths = {2, 1, 1};
529      * <STRONG>table.setWidths(widths)</STRONG>
530      * </PRE></BLOCKQUOTE>
531      * The widths will be: a width of 50% for the first column,
532      * 25% for the second and third column.
533      *
534      * @param widths an array with values
535      * @throws BadElementException
536      */

537     public void setWidths(float[] widths) throws BadElementException {
538         if (widths.length != columns) {
539             throw new BadElementException("Wrong number of columns.");
540         }
541         
542         // The sum of all values is 100%
543
float hundredPercent = 0;
544         for (int i = 0; i < columns; i++) {
545             hundredPercent += widths[i];
546         }
547         
548         // The different percentages are calculated
549
float width;
550         this.widths[columns - 1] = 100;
551         for (int i = 0; i < columns - 1; i++) {
552             width = (100.0f * widths[i]) / hundredPercent;
553             this.widths[i] = width;
554             this.widths[columns - 1] -= width;
555         }
556     }
557     
558     /**
559      * Sets the widths of the different columns (percentages).
560      * <P>
561      * You can give up relative values of borderwidths.
562      * The sum of these values will be considered 100%.
563      * The values will be recalculated as percentages of this sum.
564      *
565      * @param widths an array with values
566      * @throws DocumentException
567      */

568     public void setWidths(int[] widths) throws DocumentException {
569         float tb[] = new float[widths.length];
570         for (int k = 0; k < widths.length; ++k)
571             tb[k] = widths[k];
572         setWidths(tb);
573     }
574     
575     /**
576      * Checks if this <CODE>Table</CODE> has to fit a page.
577      *
578      * @return true if the table may not be split
579      */

580     public boolean isTableFitsPage() {
581         return tableFitsPage;
582     }
583     
584     /**
585      * Allows you to control when a page break occurs.
586      * <P>
587      * When a table doesn't fit a page, it is split in two parts.
588      * If you want to avoid this, you should set the <VAR>tableFitsPage</VAR> value to true.
589      *
590      * @param fitPage enter true if you don't want to split cells
591      */

592     public void setTableFitsPage(boolean fitPage) {
593         this.tableFitsPage = fitPage;
594         if (fitPage) setCellsFitPage(true);
595     }
596     
597     /**
598      * Checks if the cells of this <CODE>Table</CODE> have to fit a page.
599      *
600      * @return true if the cells may not be split
601      */

602     public boolean isCellsFitPage() {
603         return cellsFitPage;
604     }
605     
606     /**
607      * Allows you to control when a page break occurs.
608      * <P>
609      * When a cell doesn't fit a page, it is split in two parts.
610      * If you want to avoid this, you should set the <VAR>cellsFitPage</VAR> value to true.
611      *
612      * @param fitPage enter true if you don't want to split cells
613      */

614     public void setCellsFitPage(boolean fitPage) {
615         this.cellsFitPage = fitPage;
616     }
617     
618     /**
619      * Sets the offset of this table.
620      *
621      * Normally a newline is added before you add a Table object.
622      * This newline uses the current leading.
623      * If you want to control the space between the table and the previous
624      * element yourself, you have to set the offset of this table.
625      *
626      * @param offset the space between this table and the previous object.
627      */

628     public void setOffset(float offset) {
629         this.offset = offset;
630     }
631     
632     /**
633      * Gets the offset of this table.
634      *
635      * @return the space between this table and the previous element.
636      */

637     public float getOffset() {
638         return offset;
639     }
640     
641     /**
642      * Method to check if the Table should be converted to a PdfPTable or not.
643      * @return false if the table should be handled the oldfashioned way.
644      */

645     public boolean isConvert2pdfptable() {
646         return convert2pdfptable;
647     }
648     /**
649      * If set to true, iText will try to convert the Table to a PdfPTable.
650      * @param convert2pdfptable true if you want iText to try to convert the Table to a PdfPTable
651      */

652     public void setConvert2pdfptable(boolean convert2pdfptable) {
653         this.convert2pdfptable = convert2pdfptable;
654     }
655     
656     // methods to add content to the table
657

658     /**
659      * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE> at a certain row and column.
660      *
661      * @param aCell The <CODE>Cell</CODE> to add
662      * @param row The row where the <CODE>Cell</CODE> will be added
663      * @param column The column where the <CODE>Cell</CODE> will be added
664      * @throws BadElementException
665      */

666     public void addCell(Cell aCell, int row, int column) throws BadElementException {
667         addCell(aCell, new Point JavaDoc(row,column));
668     }
669     
670     /**
671      * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE> at a certain location.
672      *
673      * @param aCell The <CODE>Cell</CODE> to add
674      * @param aLocation The location where the <CODE>Cell</CODE> will be added
675      * @throws BadElementException
676      */

677     public void addCell(Cell aCell, Point JavaDoc aLocation) throws BadElementException {
678         if (aCell == null) throw new NullPointerException JavaDoc("addCell - cell has null-value");
679         if (aLocation == null) throw new NullPointerException JavaDoc("addCell - point has null-value");
680         if (aCell.isTable()) insertTable((Table)aCell.getElements().next(), aLocation);
681         
682         if (aLocation.x < 0) throw new BadElementException("row coordinate of location must be >= 0");
683         if ((aLocation.y <= 0) && (aLocation.y > columns)) throw new BadElementException("column coordinate of location must be >= 0 and < nr of columns");
684         if (!isValidLocation(aCell, aLocation)) throw new BadElementException("Adding a cell at the location (" + aLocation.x + "," + aLocation.y + ") with a colspan of " + aCell.getColspan() + " and a rowspan of " + aCell.getRowspan() + " is illegal (beyond boundaries/overlapping).");
685         
686         if (aCell.getBorder() == UNDEFINED) aCell.setBorder(defaultLayout.getBorder());
687         aCell.fill();
688         placeCell(rows, aCell, aLocation);
689         setCurrentLocationToNextValidPosition(aLocation);
690     }
691     
692     /**
693      * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
694      *
695      * @param cell a <CODE>Cell</CODE>
696      */

697     public void addCell(Cell cell) {
698         try {
699             addCell(cell, curPosition);
700         }
701         catch(BadElementException bee) {
702             // don't add the cell
703
}
704     }
705     
706     /**
707      * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
708      * <P>
709      * This is a shortcut for <CODE>addCell(Cell cell)</CODE>.
710      * The <CODE>Phrase</CODE> will be converted to a <CODE>Cell</CODE>.
711      *
712      * @param content a <CODE>Phrase</CODE>
713      * @throws BadElementException this should never happen
714      */

715     public void addCell(Phrase content) throws BadElementException {
716         addCell(content, curPosition);
717     }
718     
719     /**
720      * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
721      * <P>
722      * This is a shortcut for <CODE>addCell(Cell cell, Point location)</CODE>.
723      * The <CODE>Phrase</CODE> will be converted to a <CODE>Cell</CODE>.
724      *
725      * @param content a <CODE>Phrase</CODE>
726      * @param location a <CODE>Point</CODE>
727      * @throws BadElementException this should never happen
728      */

729     public void addCell(Phrase content, Point JavaDoc location) throws BadElementException {
730         Cell cell = new Cell(content);
731         cell.setBorder(defaultLayout.getBorder());
732         cell.setBorderWidth(defaultLayout.getBorderWidth());
733         cell.setBorderColor(defaultLayout.getBorderColor());
734         cell.setBackgroundColor(defaultLayout.getBackgroundColor());
735         cell.setHorizontalAlignment(defaultLayout.getHorizontalAlignment());
736         cell.setVerticalAlignment(defaultLayout.getVerticalAlignment());
737         cell.setColspan(defaultLayout.getColspan());
738         cell.setRowspan(defaultLayout.getRowspan());
739         addCell(cell, location);
740     }
741     
742     /**
743      * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
744      * <P>
745      * This is a shortcut for <CODE>addCell(Cell cell)</CODE>.
746      * The <CODE>String</CODE> will be converted to a <CODE>Cell</CODE>.
747      *
748      * @param content a <CODE>String</CODE>
749      * @throws BadElementException this should never happen
750      */

751     
752     public void addCell(String JavaDoc content) throws BadElementException {
753         addCell(new Phrase(content), curPosition);
754     }
755     
756     /**
757      * Adds a <CODE>Cell</CODE> to the <CODE>Table</CODE>.
758      * <P>
759      * This is a shortcut for <CODE>addCell(Cell cell, Point location)</CODE>.
760      * The <CODE>String</CODE> will be converted to a <CODE>Cell</CODE>.
761      *
762      * @param content a <CODE>String</CODE>
763      * @param location a <CODE>Point</CODE>
764      * @throws BadElementException this should never happen
765      */

766     public void addCell(String JavaDoc content, Point JavaDoc location) throws BadElementException {
767         addCell(new Phrase(content), location);
768     }
769     
770     /**
771      * To put a table within the existing table at the current position
772      * generateTable will of course re-arrange the widths of the columns.
773      *
774      * @param aTable the table you want to insert
775      */

776     public void insertTable(Table aTable) {
777         if (aTable == null) throw new NullPointerException JavaDoc("insertTable - table has null-value");
778         insertTable(aTable, curPosition);
779     }
780     
781     /**
782      * To put a table within the existing table at the given position
783      * generateTable will of course re-arrange the widths of the columns.
784      *
785      * @param aTable The <CODE>Table</CODE> to add
786      * @param row The row where the <CODE>Cell</CODE> will be added
787      * @param column The column where the <CODE>Cell</CODE> will be added
788      */

789     public void insertTable(Table aTable, int row, int column) {
790         if (aTable == null) throw new NullPointerException JavaDoc("insertTable - table has null-value");
791         insertTable(aTable, new Point JavaDoc(row, column));
792     }
793     
794     /**
795      * To put a table within the existing table at the given position
796      * generateTable will of course re-arrange the widths of the columns.
797      *
798      * @param aTable the table you want to insert
799      * @param aLocation a <CODE>Point</CODE>
800      */

801     public void insertTable(Table aTable, Point JavaDoc aLocation) {
802         
803         if (aTable == null) throw new NullPointerException JavaDoc("insertTable - table has null-value");
804         if (aLocation == null) throw new NullPointerException JavaDoc("insertTable - point has null-value");
805         mTableInserted = true;
806         aTable.complete();
807         
808         if (aLocation.y > columns) {
809             throw new IllegalArgumentException JavaDoc("insertTable -- wrong columnposition("+ aLocation.y + ") of location; max =" + columns);
810         }
811         
812         int rowCount = aLocation.x + 1 - rows.size();
813         int i = 0;
814         if ( rowCount > 0 ) { //create new rows ?
815
for (; i < rowCount; i++) {
816                 rows.add(new Row(columns));
817             }
818         }
819         
820         ((Row) rows.get(aLocation.x)).setElement(aTable,aLocation.y);
821         
822         setCurrentLocationToNextValidPosition(aLocation);
823     }
824     
825     /**
826      * Gives you the posibility to add columns.
827      *
828      * @param aColumns the number of columns to add
829      */

830     public void addColumns(int aColumns) {
831         ArrayList JavaDoc newRows = new ArrayList JavaDoc(rows.size());
832         
833         int newColumns = columns + aColumns;
834         Row row;
835         for (int i = 0; i < rows.size(); i++) {
836             row = new Row(newColumns);
837             for (int j = 0; j < columns; j++) {
838                 row.setElement(((Row) rows.get(i)).getCell(j) ,j);
839             }
840             for (int j = columns; j < newColumns && i < curPosition.x; j++) {
841                 row.setElement(null, j);
842             }
843             newRows.add(row);
844         }
845         // applied 1 column-fix; last column needs to have a width of 0
846
float [] newWidths = new float[newColumns];
847         System.arraycopy(widths, 0, newWidths, 0, columns);
848         for (int j = columns; j < newColumns ; j++) {
849             newWidths[j] = 0;
850         }
851         columns = newColumns;
852         widths = newWidths;
853         rows = newRows;
854     }
855     
856     /**
857      * Deletes a column in this table.
858      *
859      * @param column the number of the column that has to be deleted
860      * @throws BadElementException
861      */

862     public void deleteColumn(int column) throws BadElementException {
863         float newWidths[] = new float[--columns];
864         System.arraycopy(widths, 0, newWidths, 0, column);
865         System.arraycopy(widths, column + 1, newWidths, column, columns - column);
866         setWidths(newWidths);
867         System.arraycopy(widths, 0, newWidths, 0, columns);
868         widths = newWidths;
869         Row row;
870         int size = rows.size();
871         for (int i = 0; i < size; i++) {
872             row = (Row) rows.get(i);
873             row.deleteColumn(column);
874             rows.set(i, row);
875         }
876         if (column == columns) {
877             curPosition.setLocation(curPosition.x+1, 0);
878         }
879     }
880
881     /**
882      * Deletes a row.
883      *
884      * @param row the number of the row to delete
885      * @return boolean <CODE>true</CODE> if the row was deleted; <CODE>false</CODE> if not
886      */

887     public boolean deleteRow(int row) {
888         if (row < 0 || row >= rows.size()) {
889             return false;
890         }
891         rows.remove(row);
892         curPosition.setLocation(curPosition.x-1, curPosition.y);
893         return true;
894     }
895     
896     /**
897      * Deletes all rows in this table.
898      * (contributed by dperezcar@fcc.es)
899      */

900     public void deleteAllRows() {
901         rows.clear();
902         rows.add(new Row(columns));
903         curPosition.setLocation(0, 0);
904         lastHeaderRow = -1;
905     }
906     
907     /**
908      * Deletes the last row in this table.
909      *
910      * @return boolean <CODE>true</CODE> if the row was deleted; <CODE>false</CODE> if not
911      */

912     public boolean deleteLastRow() {
913         return deleteRow(rows.size() - 1);
914     }
915     
916     /**
917      * Will fill empty cells with valid blank <CODE>Cell</CODE>s
918      */

919     public void complete() {
920         if (mTableInserted) {
921             mergeInsertedTables(); // integrate tables in the table
922
mTableInserted = false;
923         }
924         if (autoFillEmptyCells) {
925             fillEmptyMatrixCells();
926         }
927     }
928     
929     // private helper classes
930

931     /**
932      * returns the element at the position row, column
933      * (Cast to Cell or Table)
934      *
935      * @param row
936      * @param column
937      * @return dimension
938      */

939     private Object JavaDoc getElement(int row, int column) {
940         return ((Row) rows.get(row)).getCell(column);
941     }
942     
943     /**
944      * Integrates all added tables and recalculates column widths.
945      */

946     private void mergeInsertedTables() {
947         int i=0, j=0;
948         float [] lNewWidths = null;
949         int [] lDummyWidths = new int[columns]; // to keep track in how many new cols this one will be split
950
float[][] lDummyColumnWidths = new float[columns][]; // bugfix Tony Copping
951
int [] lDummyHeights = new int[rows.size()]; // to keep track in how many new rows this one will be split
952
ArrayList JavaDoc newRows = null;
953         boolean isTable=false;
954         int lTotalRows = 0, lTotalColumns = 0;
955         int lNewMaxRows = 0, lNewMaxColumns = 0;
956         
957         Table lDummyTable = null;
958         
959         // first we'll add new columns when needed
960
// check one column at a time, find maximum needed nr of cols
961
// Search internal tables and find one with max columns
962
for (j=0; j < columns; j++) {
963             lNewMaxColumns = 1; // value to hold in how many columns the current one will be split
964
float [] tmpWidths = null;
965             for (i=0; i < rows.size(); i++) {
966                 if ( Table.class.isInstance(((Row) rows.get(i)).getCell(j)) ) {
967                     isTable=true;
968                     lDummyTable = ((Table) ((Row) rows.get(i)).getCell(j));
969                     if( tmpWidths == null) {
970                         tmpWidths = lDummyTable.widths;
971                         lNewMaxColumns=tmpWidths.length;
972                     }
973                  &n