1 50 51 package com.lowagie.text.pdf; 52 53 import java.util.ArrayList ; 54 import java.util.Iterator ; 55 56 import com.lowagie.text.Anchor; 57 import com.lowagie.text.Cell; 58 import com.lowagie.text.Chunk; 59 import com.lowagie.text.Element; 60 import com.lowagie.text.Image; 61 import com.lowagie.text.List; 62 import com.lowagie.text.ListItem; 63 import com.lowagie.text.Paragraph; 64 import com.lowagie.text.Phrase; 65 import com.lowagie.text.Rectangle; 66 67 84 85 public class PdfCell extends Rectangle { 86 87 89 92 private ArrayList lines; 93 94 97 private PdfLine line; 98 99 102 private ArrayList images; 103 104 107 private float leading; 108 109 112 private int rownumber; 113 114 117 private int rowspan; 118 119 122 private float cellspacing; 123 124 127 private float cellpadding; 128 129 132 private boolean header = false; 133 134 138 private float contentHeight = 0.0f; 139 140 144 private boolean useAscender; 145 146 149 private boolean useDescender; 150 151 154 private boolean useBorderPadding; 155 156 private int verticalAlignment; 157 158 private PdfLine firstLine; 159 private PdfLine lastLine; 160 161 163 174 175 public PdfCell(Cell cell, int rownumber, float left, float right, float top, float cellspacing, float cellpadding) { 176 super(left, top, right, top); 178 cloneNonPositionParameters(cell); 180 this.cellpadding = cellpadding; 181 this.cellspacing = cellspacing; 182 this.verticalAlignment = cell.getVerticalAlignment(); 183 this.useAscender = cell.isUseAscender(); 184 this.useDescender = cell.isUseDescender(); 185 this.useBorderPadding = cell.isUseBorderPadding(); 186 187 PdfChunk chunk; 189 Element element; 190 PdfChunk overflow; 191 lines = new ArrayList (); 192 images = new ArrayList (); 193 leading = cell.getLeading(); 194 int alignment = cell.getHorizontalAlignment(); 195 left += cellspacing + cellpadding; 196 right -= cellspacing + cellpadding; 197 198 left += getBorderWidthInside(LEFT); 199 right -= getBorderWidthInside(RIGHT); 200 201 202 contentHeight = 0; 203 204 rowspan = cell.getRowspan(); 205 206 ArrayList allActions; 207 int aCounter; 208 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, alignment); break; 217 case Element.LIST: 219 if (line != null && line.size() > 0) { 220 line.resetAlignment(); 221 addLine(line); 222 } 223 addList((List )element, left, right, alignment); 225 line = new PdfLine(left, right, alignment, leading); 226 break; 227 default: 229 allActions = new ArrayList (); 230 processActions(element, null, allActions); 231 aCounter = 0; 232 233 float currentLineLeading = leading; 234 float currentLeft = left; 235 float currentRight = right; 236 if (element instanceof Phrase) { 237 currentLineLeading = ((Phrase) element).getLeading(); 238 } 239 if (element instanceof Paragraph) { 240 Paragraph p = (Paragraph) element; 241 currentLeft += p.getIndentationLeft(); 242 currentRight -= p.getIndentationRight(); 243 } 244 if (line == null) { 245 line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading); 246 } 247 ArrayList chunks = element.getChunks(); 249 if (chunks.isEmpty()) { 250 addLine(line); line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading); 252 } 253 else { 254 for (Iterator j = chunks.iterator(); j.hasNext();) { 255 Chunk c = (Chunk) j.next(); 256 chunk = new PdfChunk(c, (PdfAction) (allActions.get(aCounter++))); 257 while ((overflow = line.add(chunk)) != null) { 258 addLine(line); 259 line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading); 260 chunk = overflow; 261 } 262 } 263 } 264 switch (element.type()) { 266 case Element.PARAGRAPH: 267 case Element.SECTION: 268 case Element.CHAPTER: 269 line.resetAlignment(); 270 flushCurrentLine(); 271 } 272 } 273 } 274 flushCurrentLine(); 275 if (lines.size() > cell.getMaxLines()) { 276 while (lines.size() > cell.getMaxLines()) { 277 removeLine(lines.size() - 1); 278 } 279 if (cell.getMaxLines() > 0) { 280 String more = cell.getShowTruncation(); 281 if (more != null && more.length() > 0) { 282 lastLine = (PdfLine) lines.get(lines.size() - 1); 284 if (lastLine.size() >= 0) { 285 PdfChunk lastChunk = lastLine.getChunk(lastLine.size() - 1); 286 float moreWidth = new PdfChunk(more, lastChunk).width(); 287 while (lastChunk.toString().length() > 0 && lastChunk.width() + moreWidth > right - left) { 288 lastChunk.setValue(lastChunk.toString().substring(0, lastChunk.length() - 1)); 290 } 291 lastChunk.setValue(lastChunk.toString() + more); 292 } else { 293 lastLine.add(new PdfChunk(new Chunk(more), null)); 294 } 295 } 296 } 297 } 298 if (useDescender && lastLine != null) { 300 contentHeight -= lastLine.getDescender(); 301 } 302 303 if (!lines.isEmpty()) { 305 firstLine = (PdfLine) lines.get(0); 306 float firstLineRealHeight = firstLineRealHeight(); 307 contentHeight -= firstLine.height(); 308 firstLine.height = firstLineRealHeight; 309 contentHeight += firstLineRealHeight; 310 } 311 312 float newBottom = top - contentHeight - (2f * cellpadding()) - (2f * cellspacing()); 313 newBottom -= getBorderWidthInside(TOP) + getBorderWidthInside(BOTTOM); 314 setBottom(newBottom); 315 316 this.rownumber = rownumber; 317 } 318 319 private void addList(List list, float left, float right, int alignment) { 320 PdfChunk chunk; 321 PdfChunk overflow; 322 ArrayList allActions = new ArrayList (); 323 processActions(list, null, allActions); 324 int aCounter = 0; 325 for (Iterator it = list.getItems().iterator(); it.hasNext();) { 326 Element ele = (Element)it.next(); 327 switch (ele.type()) { 328 case Element.LISTITEM: 329 ListItem item = (ListItem)ele; 330 line = new PdfLine(left + item.getIndentationLeft(), right, alignment, item.getLeading()); 331 line.setListItem(item); 332 for (Iterator j = item.getChunks().iterator(); j.hasNext();) { 333 chunk = new PdfChunk((Chunk) j.next(), (PdfAction) (allActions.get(aCounter++))); 334 while ((overflow = line.add(chunk)) != null) { 335 addLine(line); 336 line = new PdfLine(left + item.getIndentationLeft(), right, alignment, item.getLeading()); 337 chunk = overflow; 338 } 339 line.resetAlignment(); 340 addLine(line); 341 line = new PdfLine(left + item.getIndentationLeft(), right, alignment, leading); 342 } 343 break; 344 case Element.LIST: 345 List sublist = (List )ele; 346 addList(sublist, left + sublist.getIndentationLeft(), right, alignment); 347 break; 348 } 349 } 350 } 351 352 354 355 360 public void setBottom(float value) { 361 super.setBottom(value); 362 float firstLineRealHeight = firstLineRealHeight(); 363 364 float totalHeight = ury - value; float nonContentHeight = (cellpadding() * 2f) + (cellspacing() * 2f); 366 nonContentHeight += getBorderWidthInside(TOP) + getBorderWidthInside(BOTTOM); 367 368 float interiorHeight = totalHeight - nonContentHeight; 369 float extraHeight = 0.0f; 370 371 switch (verticalAlignment) { 372 case Element.ALIGN_BOTTOM: 373 extraHeight = interiorHeight - contentHeight; 374 break; 375 case Element.ALIGN_MIDDLE: 376 extraHeight = (interiorHeight - contentHeight) / 2.0f; 377 break; 378 default: extraHeight = 0f; 380 } 381 382 extraHeight += cellpadding() + cellspacing(); 383 extraHeight += getBorderWidthInside(TOP); 384 if (firstLine != null) { 385 firstLine.height = firstLineRealHeight + extraHeight; 386 } 387 } 388 389 395 396 public float left() { 397 return getLeft(); 398 } 399 400 401 402 403 408 409 public float getLeft() { 410 return super.getLeft(cellspacing); 411 } 412 413 419 420 public float right() { 421 return getRight(); 422 } 423 424 425 426 427 432 433 public float getRight() { 434 return super.getRight(cellspacing); 435 } 436 437 443 444 public float top() { 445 return getTop(); 446 } 447 448 449 450 451 456 457 public float getTop() { 458 return super.getTop(cellspacing); 459 } 460 461 467 468 public float bottom() { 469 return getBottom(); 470 } 471 472 473 474 475 480 481 public float getBottom() { 482 return super.getBottom(cellspacing); 483 } 484 485 487 private void addLine(PdfLine line) { 488 lines.add(line); 489 contentHeight += line.height(); 490 lastLine = line; 491 this.line = null; 492 } 493 494 private PdfLine removeLine(int index) { 495 PdfLine oldLine = (PdfLine) lines.remove(index); 496 contentHeight -= oldLine.height(); 497 if (index == 0) { 498 if (!lines.isEmpty()) { 499 firstLine = (PdfLine) lines.get(0); 500 float firstLineRealHeight = firstLineRealHeight(); 501 contentHeight -= firstLine.height(); 502 firstLine.height = firstLineRealHeight; 503 contentHeight += firstLineRealHeight; 504 } 505 } 506 return oldLine; 507 } 508 509 private void flushCurrentLine() { 510 if (line != null && line.size() > 0) { 511 addLine(line); 512 } 513 } 514 515 521 private float firstLineRealHeight() { 522 float firstLineRealHeight = 0f; 523 if (firstLine != null) { 524 PdfChunk chunk = firstLine.getChunk(0); 525 if (chunk != null) { 526 Image image = chunk.getImage(); 527 if (image != null) { 528 firstLineRealHeight = firstLine.getChunk(0).getImage().getScaledHeight(); 529 } else { 530 firstLineRealHeight = useAscender ? firstLine.getAscender() : leading; 531 } 532 } 533 } 534 return firstLineRealHeight; 535 } 536 537 544 private float getBorderWidthInside(int side) { 545 float width = 0f; 546 if (useBorderPadding) { 547 switch (side) { 548 case Rectangle.LEFT: 549 width = getBorderWidthLeft(); 550 break; 551 552 case Rectangle.RIGHT: 553 width = getBorderWidthRight(); 554 break; 555 556 case Rectangle.TOP: 557 width = getBorderWidthTop(); 558 break; 559 560 default: width = getBorderWidthBottom(); 562 break; 563 } 564 if (!isUseVariableBorders()) { 566 width = width / 2f; 567 } 568 } 569 return width; 570 } 571 572 573 583 584 private float addImage(Image i, float left, float right, float extraHeight, int alignment) { 585 Image image = Image.getInstance(i); 586 if (image.getScaledWidth() > right - left) { 587 image.scaleToFit(right - left, Float.MAX_VALUE); 588 } 589 flushCurrentLine(); 590 if (line == null) { 591 line = new PdfLine(left, right, alignment, leading); 592 } 593 PdfLine imageLine = line; 594 595 right = right - left; 597 left = 0f; 598 599 if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT) { 600 left = right - image.getScaledWidth(); 601 } else if ((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE) { 602 left = left + ((right - left - image.getScaledWidth()) / 2f); 603 } 604 Chunk imageChunk = new Chunk(image, left, 0); 605 imageLine.add(new PdfChunk(imageChunk, null)); 606 addLine(imageLine); 607 return imageLine.height(); 608 } 609 610 619 620 public ArrayList getLines(float top, float bottom) { 621 float lineHeight; 622 float currentPosition = Math.min(getTop(), top); 623 setTop(currentPosition + cellspacing); 624 ArrayList result = new ArrayList (); 625 626 if (getTop() < bottom) { 628 return result; 629 } 630 631 int size = lines.size(); 633 boolean aboveBottom = true; 634 for (int i = 0; i < size && aboveBottom; i++) { 635 line = (PdfLine) lines.get(i); 636 lineHeight = line.height(); 637 currentPosition -= lineHeight; 638 if (currentPosition > (bottom + cellpadding + getBorderWidthInside(BOTTOM))) { 640 result.add(line); 641 } else { 642 aboveBottom = false; 643 } 644 } 645 float difference = 0f; 647 if (!header) { 648 if (aboveBottom) { 649 lines = new ArrayList (); 650 contentHeight = 0f; 651 } else { 652 size = result.size(); 653 for (int i = 0; i < size; i++) { 654 line = removeLine(0); 655 difference += line.height(); 656 } 657 } 658 } 659 if (difference > 0) { 660 Image image; 661 for (Iterator i = images.iterator(); i.hasNext();) { 662 image = (Image) i.next(); 663 image.setAbsolutePosition(image.getAbsoluteX(), image.getAbsoluteY() - difference - leading); 664 } 665 } 666 return result; 667 } 668 669 678 679 public ArrayList getImages(float top, float bottom) { 680 681 if (getTop() < bottom) { 683 return new ArrayList (); 684 } 685 top = Math.min(getTop(), top); 686 Image image; 688 float height; 689 ArrayList result = new ArrayList (); 690 for (Iterator i = images.iterator(); i.hasNext() && !header;) { 692 image = (Image) i.next(); 693 height = image.getAbsoluteY(); 694 if (top - height > (bottom + cellpadding)) { 696 image.setAbsolutePosition(image.getAbsoluteX(), top - height); 697 result.add(image); 698 i.remove(); 699 } 700 } 701 return result; 702 } 703 704 709 710 boolean isHeader() { 711 return header; 712 } 713 714 717 718 void setHeader() { 719 header = true; 720 } 721 722 730 731 boolean mayBeRemoved() { 732 return (header || (lines.isEmpty() && images.isEmpty())); 733 } 734 735 740 741 public int size() { 742 return lines.size(); 743 } 744 745 750 751 public int remainingLines() { 752 if (lines.isEmpty()) return 0; 753 int result = 0; 754 int size = lines.size(); 755 PdfLine line; 756 for (int i = 0; i < size; i++) { 757 line = (PdfLine) lines.get(i); 758 if (line.size() > 0) result++; 759 } 760 return result; 761 } 762 763 768 769 public float remainingHeight() { 770 float result = 0f; 771 for (Iterator i = images.iterator(); i.hasNext();) { 772 Image image = (Image) i.next(); 773 result += image.getScaledHeight(); 774 } 775 return remainingLines() * leading + 2 * cellpadding + cellspacing + result + leading / 2.5f; 776 } 777 778 780 785 786 public float leading() { 787 return leading; 788 } 789 790 795 796 public int rownumber() { 797 return rownumber; 798 } 799 800 805 806 public int rowspan() { 807 return rowspan; 808 } 809 810 815 816 public float cellspacing() { 817 return cellspacing; 818 } 819 820 825 826 public float cellpadding() { 827 return cellpadding; 828 } 829 830 836 837 protected void processActions(Element element, PdfAction action, ArrayList allActions) { 838 if (element.type() == Element.ANCHOR) { 839 String url = ((Anchor) element).getReference(); 840 if (url != null) { 841 action = new PdfAction(url); 842 } 843 } 844 Iterator i; 845 switch (element.type()) { 846 case Element.PHRASE: 847 case Element.SECTION: 848 case Element.ANCHOR: 849 case Element.CHAPTER: 850 case Element.LISTITEM: 851 case Element.PARAGRAPH: 852 for (i = ((ArrayList ) element).iterator(); i.hasNext();) { 853 processActions((Element) i.next(), action, allActions); 854 } 855 break; 856 case Element.CHUNK: 857 allActions.add(action); 858 break; 859 case Element.LIST: 860 for (i = ((List ) element).getItems().iterator(); i.hasNext();) { 861 processActions((Element) i.next(), action, allActions); 862 } 863 break; 864 default: 865 int n = element.getChunks().size(); 866 while (n-- > 0) 867 allActions.add(action); 868 break; 869 } 870 } 871 872 875 private int groupNumber; 876 877 882 883 public int getGroupNumber() { 884 return groupNumber; 885 } 886 887 891 892 void setGroupNumber(int number) { 893 groupNumber = number; 894 } 895 896 903 904 public Rectangle rectangle(float top, float bottom) { 905 Rectangle tmp = new Rectangle(getLeft(), getBottom(), getRight(), getTop()); 906 tmp.cloneNonPositionParameters(this); 907 if (getTop() > top) { 908 tmp.setTop(top); 909 tmp.setBorder(border - (border & TOP)); 910 } 911 if (getBottom() < bottom) { 912 tmp.setBottom(bottom); 913 tmp.setBorder(border - (border & BOTTOM)); 914 } 915 return tmp; 916 } 917 918 922 public void setUseAscender(boolean use) { 923 useAscender = use; 924 } 925 926 930 public boolean isUseAscender() { 931 return useAscender; 932 } 933 934 938 public void setUseDescender(boolean use) { 939 useDescender = use; 940 } 941 942 946 public boolean isUseDescender() { 947 return useDescender; 948 } 949 950 954 public void setUseBorderPadding(boolean use) { 955 useBorderPadding = use; 956 } 957 958 962 public boolean isUseBorderPadding() { 963 return useBorderPadding; 964 } 965 966 } 967 | Popular Tags |