001: /*
002: * $Id: PdfCell.java 2762 2007-05-16 16:07:09Z psoares33 $
003: * $Name$
004: *
005: * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */
050:
051: package com.lowagie.text.pdf;
052:
053: import java.util.ArrayList;
054: import java.util.Iterator;
055:
056: import com.lowagie.text.Anchor;
057: import com.lowagie.text.Cell;
058: import com.lowagie.text.Chunk;
059: import com.lowagie.text.Element;
060: import com.lowagie.text.Image;
061: import com.lowagie.text.List;
062: import com.lowagie.text.ListItem;
063: import com.lowagie.text.Paragraph;
064: import com.lowagie.text.Phrase;
065: import com.lowagie.text.Rectangle;
066:
067: /**
068: * A <CODE>PdfCell</CODE> is the PDF translation of a <CODE>Cell</CODE>.
069: * <P>
070: * A <CODE>PdfCell</CODE> is an <CODE>ArrayList</CODE> of <CODE>PdfLine</CODE>s.
071: * <P>
072: * When using variable borders ({@link com.lowagie.text.Rectangle#isUseVariableBorders isUseVariableBorders()} == true),
073: * the borders are drawn completely inside the cell Rectangle
074: * so that adjacent cell borders will not overlap.
075: * Otherwise, the borders are drawn on top of the edges of the
076: * cell Rectangle and will overlap the borders of adjacent
077: * cells.
078: *
079: * @see com.lowagie.text.Rectangle
080: * @see com.lowagie.text.Cell
081: * @see PdfLine
082: * @see PdfTable
083: */
084:
085: public class PdfCell extends Rectangle {
086:
087: // membervariables
088:
089: /**
090: * These are the PdfLines in the Cell.
091: */
092: private ArrayList lines;
093:
094: /**
095: * These are the PdfLines in the Cell.
096: */
097: private PdfLine line;
098:
099: /**
100: * These are the Images in the Cell.
101: */
102: private ArrayList images;
103:
104: /**
105: * This is the leading of the lines.
106: */
107: private float leading;
108:
109: /**
110: * This is the number of the row the cell is in.
111: */
112: private int rownumber;
113:
114: /**
115: * This is the rowspan of the cell.
116: */
117: private int rowspan;
118:
119: /**
120: * This is the cellspacing of the cell.
121: */
122: private float cellspacing;
123:
124: /**
125: * This is the cellpadding of the cell.
126: */
127: private float cellpadding;
128:
129: /**
130: * Indicates if this cell belongs to the header of a <CODE>PdfTable</CODE>
131: */
132: private boolean header = false;
133:
134: /**
135: * This is the total height of the content of the cell. Note that the actual cell
136: * height may be larger due to another cell on the row *
137: */
138: private float contentHeight = 0.0f;
139:
140: /**
141: * Indicates that the largest ascender height should be used to
142: * determine the height of the first line. Setting this to true can help
143: * with vertical alignment problems. */
144: private boolean useAscender;
145:
146: /**
147: * Indicates that the largest descender height should be added to the height of
148: * the last line (so characters like y don't dip into the border). */
149: private boolean useDescender;
150:
151: /**
152: * Adjusts the cell contents to compensate for border widths.
153: */
154: private boolean useBorderPadding;
155:
156: private int verticalAlignment;
157:
158: private PdfLine firstLine;
159: private PdfLine lastLine;
160:
161: // constructors
162:
163: /**
164: * Constructs a <CODE>PdfCell</CODE>-object.
165: *
166: * @param cell the original <CODE>Cell</CODE>
167: * @param rownumber the number of the <CODE>Row</CODE> the <CODE>Cell</CODE> was in.
168: * @param left the left border of the <CODE>PdfCell</CODE>
169: * @param right the right border of the <CODE>PdfCell</CODE>
170: * @param top the top border of the <CODE>PdfCell</CODE>
171: * @param cellspacing the cellspacing of the <CODE>Table</CODE>
172: * @param cellpadding the cellpadding of the <CODE>Table</CODE>
173: */
174:
175: public PdfCell(Cell cell, int rownumber, float left, float right,
176: float top, float cellspacing, float cellpadding) {
177: // constructs a Rectangle (the bottomvalue will be changed afterwards)
178: super (left, top, right, top);
179: // copying the other Rectangle attributes from class Cell
180: cloneNonPositionParameters(cell);
181: this .cellpadding = cellpadding;
182: this .cellspacing = cellspacing;
183: this .verticalAlignment = cell.getVerticalAlignment();
184: this .useAscender = cell.isUseAscender();
185: this .useDescender = cell.isUseDescender();
186: this .useBorderPadding = cell.isUseBorderPadding();
187:
188: // initialisation of some parameters
189: PdfChunk chunk;
190: Element element;
191: PdfChunk overflow;
192: lines = new ArrayList();
193: images = new ArrayList();
194: leading = cell.getLeading();
195: int alignment = cell.getHorizontalAlignment();
196: left += cellspacing + cellpadding;
197: right -= cellspacing + cellpadding;
198:
199: left += getBorderWidthInside(LEFT);
200: right -= getBorderWidthInside(RIGHT);
201:
202: contentHeight = 0;
203:
204: rowspan = cell.getRowspan();
205:
206: ArrayList allActions;
207: int aCounter;
208: // we loop over all the elements of the cell
209: for (Iterator i = cell.getElements(); i.hasNext();) {
210: element = (Element) i.next();
211: switch (element.type()) {
212: case Element.JPEG:
213: case Element.IMGRAW:
214: case Element.IMGTEMPLATE:
215: addImage((Image) element, left, right, 0.4f * leading,
216: alignment); //
217: break;
218: // if the element is a list
219: case Element.LIST:
220: if (line != null && line.size() > 0) {
221: line.resetAlignment();
222: addLine(line);
223: }
224: // we loop over all the listitems
225: addList((List) element, left, right, alignment);
226: line = new PdfLine(left, right, alignment, leading);
227: break;
228: // if the element is something else
229: default:
230: allActions = new ArrayList();
231: processActions(element, null, allActions);
232: aCounter = 0;
233:
234: float currentLineLeading = leading;
235: float currentLeft = left;
236: float currentRight = right;
237: if (element instanceof Phrase) {
238: currentLineLeading = ((Phrase) element)
239: .getLeading();
240: }
241: if (element instanceof Paragraph) {
242: Paragraph p = (Paragraph) element;
243: currentLeft += p.getIndentationLeft();
244: currentRight -= p.getIndentationRight();
245: }
246: if (line == null) {
247: line = new PdfLine(currentLeft, currentRight,
248: alignment, currentLineLeading);
249: }
250: // we loop over the chunks
251: ArrayList chunks = element.getChunks();
252: if (chunks.isEmpty()) {
253: addLine(line); // add empty line - all cells need some lines even if they are empty
254: line = new PdfLine(currentLeft, currentRight,
255: alignment, currentLineLeading);
256: } else {
257: for (Iterator j = chunks.iterator(); j.hasNext();) {
258: Chunk c = (Chunk) j.next();
259: chunk = new PdfChunk(c, (PdfAction) (allActions
260: .get(aCounter++)));
261: while ((overflow = line.add(chunk)) != null) {
262: addLine(line);
263: line = new PdfLine(currentLeft,
264: currentRight, alignment,
265: currentLineLeading);
266: chunk = overflow;
267: }
268: }
269: }
270: // if the element is a paragraph, section or chapter, we reset the alignment and add the line
271: switch (element.type()) {
272: case Element.PARAGRAPH:
273: case Element.SECTION:
274: case Element.CHAPTER:
275: line.resetAlignment();
276: flushCurrentLine();
277: }
278: }
279: }
280: flushCurrentLine();
281: if (lines.size() > cell.getMaxLines()) {
282: while (lines.size() > cell.getMaxLines()) {
283: removeLine(lines.size() - 1);
284: }
285: if (cell.getMaxLines() > 0) {
286: String more = cell.getShowTruncation();
287: if (more != null && more.length() > 0) {
288: // Denote that the content has been truncated
289: lastLine = (PdfLine) lines.get(lines.size() - 1);
290: if (lastLine.size() >= 0) {
291: PdfChunk lastChunk = lastLine.getChunk(lastLine
292: .size() - 1);
293: float moreWidth = new PdfChunk(more, lastChunk)
294: .width();
295: while (lastChunk.toString().length() > 0
296: && lastChunk.width() + moreWidth > right
297: - left) {
298: // Remove characters to leave room for the 'more' indicator
299: lastChunk.setValue(lastChunk.toString()
300: .substring(0,
301: lastChunk.length() - 1));
302: }
303: lastChunk.setValue(lastChunk.toString() + more);
304: } else {
305: lastLine
306: .add(new PdfChunk(new Chunk(more), null));
307: }
308: }
309: }
310: }
311: // we set some additional parameters
312: if (useDescender && lastLine != null) {
313: contentHeight -= lastLine.getDescender();
314: }
315:
316: // adjust first line height so that it touches the top
317: if (!lines.isEmpty()) {
318: firstLine = (PdfLine) lines.get(0);
319: float firstLineRealHeight = firstLineRealHeight();
320: contentHeight -= firstLine.height();
321: firstLine.height = firstLineRealHeight;
322: contentHeight += firstLineRealHeight;
323: }
324:
325: float newBottom = top - contentHeight - (2f * cellpadding())
326: - (2f * cellspacing());
327: newBottom -= getBorderWidthInside(TOP)
328: + getBorderWidthInside(BOTTOM);
329: setBottom(newBottom);
330:
331: this .rownumber = rownumber;
332: }
333:
334: private void addList(List list, float left, float right,
335: int alignment) {
336: PdfChunk chunk;
337: PdfChunk overflow;
338: ArrayList allActions = new ArrayList();
339: processActions(list, null, allActions);
340: int aCounter = 0;
341: for (Iterator it = list.getItems().iterator(); it.hasNext();) {
342: Element ele = (Element) it.next();
343: switch (ele.type()) {
344: case Element.LISTITEM:
345: ListItem item = (ListItem) ele;
346: line = new PdfLine(left + item.getIndentationLeft(),
347: right, alignment, item.getLeading());
348: line.setListItem(item);
349: for (Iterator j = item.getChunks().iterator(); j
350: .hasNext();) {
351: chunk = new PdfChunk((Chunk) j.next(),
352: (PdfAction) (allActions.get(aCounter++)));
353: while ((overflow = line.add(chunk)) != null) {
354: addLine(line);
355: line = new PdfLine(left
356: + item.getIndentationLeft(), right,
357: alignment, item.getLeading());
358: chunk = overflow;
359: }
360: line.resetAlignment();
361: addLine(line);
362: line = new PdfLine(
363: left + item.getIndentationLeft(), right,
364: alignment, leading);
365: }
366: break;
367: case Element.LIST:
368: List sublist = (List) ele;
369: addList(sublist, left + sublist.getIndentationLeft(),
370: right, alignment);
371: break;
372: }
373: }
374: }
375:
376: // overriding of the Rectangle methods
377:
378: /**
379: * Sets the bottom of the Rectangle and determines the proper {link #verticalOffset}
380: * to appropriately align the contents vertically.
381: * @param value
382: */
383: public void setBottom(float value) {
384: super .setBottom(value);
385: float firstLineRealHeight = firstLineRealHeight();
386:
387: float totalHeight = ury - value; // can't use top (already compensates for cellspacing)
388: float nonContentHeight = (cellpadding() * 2f)
389: + (cellspacing() * 2f);
390: nonContentHeight += getBorderWidthInside(TOP)
391: + getBorderWidthInside(BOTTOM);
392:
393: float interiorHeight = totalHeight - nonContentHeight;
394: float extraHeight = 0.0f;
395:
396: switch (verticalAlignment) {
397: case Element.ALIGN_BOTTOM:
398: extraHeight = interiorHeight - contentHeight;
399: break;
400: case Element.ALIGN_MIDDLE:
401: extraHeight = (interiorHeight - contentHeight) / 2.0f;
402: break;
403: default: // ALIGN_TOP
404: extraHeight = 0f;
405: }
406:
407: extraHeight += cellpadding() + cellspacing();
408: extraHeight += getBorderWidthInside(TOP);
409: if (firstLine != null) {
410: firstLine.height = firstLineRealHeight + extraHeight;
411: }
412: }
413:
414: /**
415: * Returns the lower left x-coordinaat.
416: *
417: * @return the lower left x-coordinaat
418: * @deprecated Use {@link #getLeft()} instead
419: */
420:
421: public float left() {
422: return getLeft();
423: }
424:
425: /**
426: * Returns the lower left x-coordinaat.
427: *
428: * @return the lower left x-coordinaat
429: */
430:
431: public float getLeft() {
432: return super .getLeft(cellspacing);
433: }
434:
435: /**
436: * Returns the upper right x-coordinate.
437: *
438: * @return the upper right x-coordinate
439: * @deprecated Use {@link #getRight()} instead
440: */
441:
442: public float right() {
443: return getRight();
444: }
445:
446: /**
447: * Returns the upper right x-coordinate.
448: *
449: * @return the upper right x-coordinate
450: */
451:
452: public float getRight() {
453: return super .getRight(cellspacing);
454: }
455:
456: /**
457: * Returns the upper right y-coordinate.
458: *
459: * @return the upper right y-coordinate
460: * @deprecated Use {@link #getTop()} instead
461: */
462:
463: public float top() {
464: return getTop();
465: }
466:
467: /**
468: * Returns the upper right y-coordinate.
469: *
470: * @return the upper right y-coordinate
471: */
472:
473: public float getTop() {
474: return super .getTop(cellspacing);
475: }
476:
477: /**
478: * Returns the lower left y-coordinate.
479: *
480: * @return the lower left y-coordinate
481: * @deprecated Use {@link #getBottom()} instead
482: */
483:
484: public float bottom() {
485: return getBottom();
486: }
487:
488: /**
489: * Returns the lower left y-coordinate.
490: *
491: * @return the lower left y-coordinate
492: */
493:
494: public float getBottom() {
495: return super .getBottom(cellspacing);
496: }
497:
498: // methods
499:
500: private void addLine(PdfLine line) {
501: lines.add(line);
502: contentHeight += line.height();
503: lastLine = line;
504: this .line = null;
505: }
506:
507: private PdfLine removeLine(int index) {
508: PdfLine oldLine = (PdfLine) lines.remove(index);
509: contentHeight -= oldLine.height();
510: if (index == 0) {
511: if (!lines.isEmpty()) {
512: firstLine = (PdfLine) lines.get(0);
513: float firstLineRealHeight = firstLineRealHeight();
514: contentHeight -= firstLine.height();
515: firstLine.height = firstLineRealHeight;
516: contentHeight += firstLineRealHeight;
517: }
518: }
519: return oldLine;
520: }
521:
522: private void flushCurrentLine() {
523: if (line != null && line.size() > 0) {
524: addLine(line);
525: }
526: }
527:
528: /**
529: * Calculates what the height of the first line should be so that the content will be
530: * flush with the top. For text, this is the height of the ascender. For an image,
531: * it is the actual height of the image.
532: * @return the real height of the first line
533: */
534: private float firstLineRealHeight() {
535: float firstLineRealHeight = 0f;
536: if (firstLine != null) {
537: PdfChunk chunk = firstLine.getChunk(0);
538: if (chunk != null) {
539: Image image = chunk.getImage();
540: if (image != null) {
541: firstLineRealHeight = firstLine.getChunk(0)
542: .getImage().getScaledHeight();
543: } else {
544: firstLineRealHeight = useAscender ? firstLine
545: .getAscender() : leading;
546: }
547: }
548: }
549: return firstLineRealHeight;
550: }
551:
552: /**
553: * Gets the amount of the border for the specified side that is inside the Rectangle.
554: * For non-variable width borders this is only 1/2 the border width on that side. This
555: * always returns 0 if {@link #useBorderPadding} is false;
556: * @param side the side to check. One of the side constants in {@link com.lowagie.text.Rectangle}
557: * @return the borderwidth inside the cell
558: */
559: private float getBorderWidthInside(int side) {
560: float width = 0f;
561: if (useBorderPadding) {
562: switch (side) {
563: case Rectangle.LEFT:
564: width = getBorderWidthLeft();
565: break;
566:
567: case Rectangle.RIGHT:
568: width = getBorderWidthRight();
569: break;
570:
571: case Rectangle.TOP:
572: width = getBorderWidthTop();
573: break;
574:
575: default: // default and BOTTOM
576: width = getBorderWidthBottom();
577: break;
578: }
579: // non-variable (original style) borders overlap the rectangle (only 1/2 counts)
580: if (!isUseVariableBorders()) {
581: width = width / 2f;
582: }
583: }
584: return width;
585: }
586:
587: /**
588: * Adds an image to this Cell.
589: *
590: * @param i the image to add
591: * @param left the left border
592: * @param right the right border
593: * @param extraHeight extra height to add above image
594: * @param alignment horizontal alignment (constant from Element class)
595: * @return the height of the image
596: */
597:
598: private float addImage(Image i, float left, float right,
599: float extraHeight, int alignment) {
600: Image image = Image.getInstance(i);
601: if (image.getScaledWidth() > right - left) {
602: image.scaleToFit(right - left, Float.MAX_VALUE);
603: }
604: flushCurrentLine();
605: if (line == null) {
606: line = new PdfLine(left, right, alignment, leading);
607: }
608: PdfLine imageLine = line;
609:
610: // left and right in chunk is relative to the start of the line
611: right = right - left;
612: left = 0f;
613:
614: if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT) {
615: left = right - image.getScaledWidth();
616: } else if ((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE) {
617: left = left
618: + ((right - left - image.getScaledWidth()) / 2f);
619: }
620: Chunk imageChunk = new Chunk(image, left, 0);
621: imageLine.add(new PdfChunk(imageChunk, null));
622: addLine(imageLine);
623: return imageLine.height();
624: }
625:
626: /**
627: * Gets the lines of a cell that can be drawn between certain limits.
628: * <P>
629: * Remark: all the lines that can be drawn are removed from the object!
630: *
631: * @param top the top of the part of the table that can be drawn
632: * @param bottom the bottom of the part of the table that can be drawn
633: * @return an <CODE>ArrayList</CODE> of <CODE>PdfLine</CODE>s
634: */
635:
636: public ArrayList getLines(float top, float bottom) {
637: float lineHeight;
638: float currentPosition = Math.min(getTop(), top);
639: setTop(currentPosition + cellspacing);
640: ArrayList result = new ArrayList();
641:
642: // if the bottom of the page is higher than the top of the cell: do nothing
643: if (getTop() < bottom) {
644: return result;
645: }
646:
647: // we loop over the lines
648: int size = lines.size();
649: boolean aboveBottom = true;
650: for (int i = 0; i < size && aboveBottom; i++) {
651: line = (PdfLine) lines.get(i);
652: lineHeight = line.height();
653: currentPosition -= lineHeight;
654: // if the currentPosition is higher than the bottom, we add the line to the result
655: if (currentPosition > (bottom + cellpadding + getBorderWidthInside(BOTTOM))) {
656: result.add(line);
657: } else {
658: aboveBottom = false;
659: }
660: }
661: // if the bottom of the cell is higher than the bottom of the page, the cell is written, so we can remove all lines
662: float difference = 0f;
663: if (!header) {
664: if (aboveBottom) {
665: lines = new ArrayList();
666: contentHeight = 0f;
667: } else {
668: size = result.size();
669: for (int i = 0; i < size; i++) {
670: line = removeLine(0);
671: difference += line.height();
672: }
673: }
674: }
675: if (difference > 0) {
676: Image image;
677: for (Iterator i = images.iterator(); i.hasNext();) {
678: image = (Image) i.next();
679: image.setAbsolutePosition(image.getAbsoluteX(), image
680: .getAbsoluteY()
681: - difference - leading);
682: }
683: }
684: return result;
685: }
686:
687: /**
688: * Gets the images of a cell that can be drawn between certain limits.
689: * <P>
690: * Remark: all the lines that can be drawn are removed from the object!
691: *
692: * @param top the top of the part of the table that can be drawn
693: * @param bottom the bottom of the part of the table that can be drawn
694: * @return an <CODE>ArrayList</CODE> of <CODE>Image</CODE>s
695: */
696:
697: public ArrayList getImages(float top, float bottom) {
698:
699: // if the bottom of the page is higher than the top of the cell: do nothing
700: if (getTop() < bottom) {
701: return new ArrayList();
702: }
703: top = Math.min(getTop(), top);
704: // initialisations
705: Image image;
706: float height;
707: ArrayList result = new ArrayList();
708: // we loop over the images
709: for (Iterator i = images.iterator(); i.hasNext() && !header;) {
710: image = (Image) i.next();
711: height = image.getAbsoluteY();
712: // if the currentPosition is higher than the bottom, we add the line to the result
713: if (top - height > (bottom + cellpadding)) {
714: image.setAbsolutePosition(image.getAbsoluteX(), top
715: - height);
716: result.add(image);
717: i.remove();
718: }
719: }
720: return result;
721: }
722:
723: /**
724: * Checks if this cell belongs to the header of a <CODE>PdfTable</CODE>.
725: *
726: * @return <CODE>void</CODE>
727: */
728:
729: boolean isHeader() {
730: return header;
731: }
732:
733: /**
734: * Indicates that this cell belongs to the header of a <CODE>PdfTable</CODE>.
735: */
736:
737: void setHeader() {
738: header = true;
739: }
740:
741: /**
742: * Checks if the cell may be removed.
743: * <P>
744: * Headers may allways be removed, even if they are drawn only partially:
745: * they will be repeated on each following page anyway!
746: *
747: * @return <CODE>true</CODE> if all the lines are allready drawn; <CODE>false</CODE> otherwise.
748: */
749:
750: boolean mayBeRemoved() {
751: return (header || (lines.isEmpty() && images.isEmpty()));
752: }
753:
754: /**
755: * Returns the number of lines in the cell.
756: *
757: * @return a value
758: */
759:
760: public int size() {
761: return lines.size();
762: }
763:
764: /**
765: * Returns the number of lines in the cell that are not empty.
766: *
767: * @return a value
768: */
769:
770: public int remainingLines() {
771: if (lines.isEmpty())
772: return 0;
773: int result = 0;
774: int size = lines.size();
775: PdfLine line;
776: for (int i = 0; i < size; i++) {
777: line = (PdfLine) lines.get(i);
778: if (line.size() > 0)
779: result++;
780: }
781: return result;
782: }
783:
784: /**
785: * Returns the height needed to draw the remaining text.
786: *
787: * @return a height
788: */
789:
790: public float remainingHeight() {
791: float result = 0f;
792: for (Iterator i = images.iterator(); i.hasNext();) {
793: Image image = (Image) i.next();
794: result += image.getScaledHeight();
795: }
796: return remainingLines() * leading + 2 * cellpadding
797: + cellspacing + result + leading / 2.5f;
798: }
799:
800: // methods to retrieve membervariables
801:
802: /**
803: * Gets the leading of a cell.
804: *
805: * @return the leading of the lines is the cell.
806: */
807:
808: public float leading() {
809: return leading;
810: }
811:
812: /**
813: * Gets the number of the row this cell is in..
814: *
815: * @return a number
816: */
817:
818: public int rownumber() {
819: return rownumber;
820: }
821:
822: /**
823: * Gets the rowspan of a cell.
824: *
825: * @return the rowspan of the cell
826: */
827:
828: public int rowspan() {
829: return rowspan;
830: }
831:
832: /**
833: * Gets the cellspacing of a cell.
834: *
835: * @return a value
836: */
837:
838: public float cellspacing() {
839: return cellspacing;
840: }
841:
842: /**
843: * Gets the cellpadding of a cell..
844: *
845: * @return a value
846: */
847:
848: public float cellpadding() {
849: return cellpadding;
850: }
851:
852: /**
853: * Processes all actions contained in the cell.
854: * @param element an element in the cell
855: * @param action an action that should be coupled to the cell
856: * @param allActions
857: */
858:
859: protected void processActions(Element element, PdfAction action,
860: ArrayList allActions) {
861: if (element.type() == Element.ANCHOR) {
862: String url = ((Anchor) element).getReference();
863: if (url != null) {
864: action = new PdfAction(url);
865: }
866: }
867: Iterator i;
868: switch (element.type()) {
869: case Element.PHRASE:
870: case Element.SECTION:
871: case Element.ANCHOR:
872: case Element.CHAPTER:
873: case Element.LISTITEM:
874: case Element.PARAGRAPH:
875: for (i = ((ArrayList) element).iterator(); i.hasNext();) {
876: processActions((Element) i.next(), action, allActions);
877: }
878: break;
879: case Element.CHUNK:
880: allActions.add(action);
881: break;
882: case Element.LIST:
883: for (i = ((List) element).getItems().iterator(); i
884: .hasNext();) {
885: processActions((Element) i.next(), action, allActions);
886: }
887: break;
888: default:
889: int n = element.getChunks().size();
890: while (n-- > 0)
891: allActions.add(action);
892: break;
893: }
894: }
895:
896: /**
897: * This is the number of the group the cell is in.
898: */
899: private int groupNumber;
900:
901: /**
902: * Gets the number of the group this cell is in..
903: *
904: * @return a number
905: */
906:
907: public int getGroupNumber() {
908: return groupNumber;
909: }
910:
911: /**
912: * Sets the group number.
913: * @param number
914: */
915:
916: void setGroupNumber(int number) {
917: groupNumber = number;
918: }
919:
920: /**
921: * Gets a Rectangle that is altered to fit on the page.
922: *
923: * @param top the top position
924: * @param bottom the bottom position
925: * @return a <CODE>Rectangle</CODE>
926: */
927:
928: public Rectangle rectangle(float top, float bottom) {
929: Rectangle tmp = new Rectangle(getLeft(), getBottom(),
930: getRight(), getTop());
931: tmp.cloneNonPositionParameters(this );
932: if (getTop() > top) {
933: tmp.setTop(top);
934: tmp.setBorder(border - (border & TOP));
935: }
936: if (getBottom() < bottom) {
937: tmp.setBottom(bottom);
938: tmp.setBorder(border - (border & BOTTOM));
939: }
940: return tmp;
941: }
942:
943: /**
944: * Sets the value of {@link #useAscender}.
945: * @param use use ascender height if true
946: */
947: public void setUseAscender(boolean use) {
948: useAscender = use;
949: }
950:
951: /**
952: * Gets the value of {@link #useAscender}
953: * @return useAscender
954: */
955: public boolean isUseAscender() {
956: return useAscender;
957: }
958:
959: /**
960: * Sets the value of {@link #useDescender}.
961: * @param use use descender height if true
962: */
963: public void setUseDescender(boolean use) {
964: useDescender = use;
965: }
966:
967: /**
968: * gets the value of {@link #useDescender }
969: * @return useDescender
970: */
971: public boolean isUseDescender() {
972: return useDescender;
973: }
974:
975: /**
976: * Sets the value of {@link #useBorderPadding}.
977: * @param use adjust layour for borders if true
978: */
979: public void setUseBorderPadding(boolean use) {
980: useBorderPadding = use;
981: }
982:
983: /**
984: * Gets the value of {@link #useBorderPadding}.
985: * @return useBorderPadding
986: */
987: public boolean isUseBorderPadding() {
988: return useBorderPadding;
989: }
990:
991: }
|