1 14 package org.compiere.print.layout; 15 16 import java.awt.*; 17 import java.awt.geom.*; 18 import java.awt.font.*; 19 import java.awt.image.*; 20 import java.text.*; 21 import java.util.*; 22 import java.util.regex.*; 23 24 import org.compiere.print.*; 25 import org.compiere.model.*; 26 import org.compiere.util.*; 27 28 48 public class TableElement extends PrintElement 49 { 50 83 public TableElement (ValueNamePair[] columnHeader, 84 int[] columnMaxWidth, int[] columnMaxHeight, String [] columnJustification, 85 boolean[] fixedWidth, boolean lastLineFunction, boolean multiLineHeader, 86 Object [][] data, KeyNamePair[] pk, String pkColumnName, 87 int pageNoStart, Rectangle firstPage, Rectangle nextPages, int repeatedColumns, HashMap additionalLines, 88 HashMap rowColFont, HashMap rowColColor, HashMap rowColBackground, 89 MPrintTableFormat tFormat, ArrayList pageBreak) 90 { 91 Log.trace(Log.l4_Data, "TableElement", "Cols=" + columnHeader.length + ", Rows=" + data.length); 92 m_columnHeader = columnHeader; 93 m_columnMaxWidth = columnMaxWidth; 94 m_columnMaxHeight = columnMaxHeight; 95 m_columnJustification = columnJustification; 96 m_lastLineFunction = lastLineFunction; 97 m_fixedWidth = fixedWidth; 98 m_multiLineHeader = multiLineHeader; 100 m_data = data; 101 m_pk = pk; 102 m_pkColumnName = pkColumnName; 103 m_pageNoStart = pageNoStart; 105 m_firstPage = firstPage; 106 m_nextPages = nextPages; 107 m_repeatedColumns = repeatedColumns; 108 m_additionalLines = additionalLines; 109 Point p = new Point (ALL, ALL); 111 m_rowColFont = rowColFont; 112 m_baseFont = (Font)m_rowColFont.get(p); 113 if (m_baseFont == null) 114 m_baseFont = new Font(null); 115 m_rowColColor = rowColColor; 116 m_baseColor = (Color)m_rowColColor.get(p); 117 if (m_baseColor == null) 118 m_baseColor = Color.black; 119 m_rowColBackground = rowColBackground; 120 m_baseBackground = (Color)m_rowColBackground.get(p); 121 if (m_baseBackground == null) 122 m_baseBackground = Color.white; 123 m_tFormat = tFormat; 124 125 m_pageBreak = pageBreak; 127 for (int i = 0; i < m_pageBreak.size(); i++) 128 { 129 Integer row = (Integer )m_pageBreak.get(i); 130 while ((i + 1) < m_pageBreak.size()) 131 { 132 Integer nextRow = (Integer )m_pageBreak.get(i+1); 133 if ((row.intValue()+1) == nextRow.intValue()) 134 { 135 Log.trace(8, "Removing PageBreak row=" + row); 136 m_pageBreak.remove(i); 137 row = nextRow; 138 } 139 else 140 break; 141 } 142 } 144 waitForLoad(LayoutEngine.IMAGE_TRUE); 146 waitForLoad(LayoutEngine.IMAGE_FALSE); 147 } 149 150 private ValueNamePair[] m_columnHeader; 151 152 private int[] m_columnMaxWidth; 153 154 private int[] m_columnMaxHeight; 155 156 private String [] m_columnJustification; 157 158 private boolean[] m_fixedWidth; 159 160 private boolean m_multiLineHeader; 161 162 private boolean m_lastLineFunction; 163 164 private Object [][] m_data; 165 166 private KeyNamePair[] m_pk; 167 168 private String m_pkColumnName; 169 170 private int m_pageNoStart; 171 172 private Rectangle m_firstPage; 173 174 private Rectangle m_nextPages; 175 176 177 private int m_repeatedColumns; 178 179 180 private Font m_baseFont; 181 182 private HashMap m_rowColFont; 183 184 private Color m_baseColor; 185 186 private HashMap m_rowColColor; 187 188 private Color m_baseBackground; 189 190 private HashMap m_rowColBackground; 191 192 private MPrintTableFormat m_tFormat; 193 194 private ArrayList m_pageBreak; 195 196 197 198 private ArrayList m_columnWidths = new ArrayList(); 199 200 private ArrayList m_rowHeights = new ArrayList(); 201 202 private int m_headerHeight = 0; 203 204 205 private ArrayList m_firstRowOnPage = new ArrayList(); 206 207 private ArrayList m_firstColumnOnPage = new ArrayList(); 208 209 private ArrayList m_pageHeight = new ArrayList(); 210 211 212 private HashMap m_rowColDrillDown = new HashMap(); 213 214 215 216 private HashMap m_additionalLines = new HashMap(); 217 218 private HashMap m_additionalLineData = new HashMap(); 219 220 221 222 223 public static final int HEADER_ROW = -2; 224 225 public static final int ALL = -1; 226 227 228 private static final int H_GAP = 2; 229 230 private static final int V_GAP = 2; 231 232 private static final int V_LINE = 1; 233 234 private static final int H_LINE = 1; 235 236 237 238 239 244 protected boolean calculateSize() 245 { 246 if (p_sizeCalculated) 247 return true; 248 249 Log.trace(Log.l5_DData, "TableElement.calculateSize"); 250 p_width = 0; 251 m_additionalLineData = new HashMap(); 253 float dynMxColumnWidth = m_firstPage.width / 2; 255 256 int rows = m_data.length; 258 int cols = m_columnHeader.length; 259 Dimension2DImpl[][] dataSizes = new Dimension2DImpl[rows][cols]; 261 Dimension2DImpl[] headerSizes = new Dimension2DImpl[cols]; 262 FontRenderContext frc = new FontRenderContext(null, true, true); 263 264 for (int dataCol = 0; dataCol < cols; dataCol++) 266 { 267 int col = dataCol; 268 if (m_additionalLines.containsKey(new Integer (dataCol))) 270 { 271 col = ((Integer )m_additionalLines.get(new Integer (dataCol))).intValue(); 272 Log.trace(9, "DataColumn=" + dataCol + ", BelowColumn=" + col); 273 } 274 float colWidth = 0; 275 for (int row = 0; row < rows; row++) 276 { 277 Object dataItem = m_data[row][dataCol]; 278 if (dataItem == null) 279 { 280 dataSizes[row][dataCol] = new Dimension2DImpl(); 281 continue; 282 } 283 String string = dataItem.toString(); 284 if (string.length() == 0) 285 { 286 dataSizes[row][dataCol] = new Dimension2DImpl(); 287 continue; 288 } 289 Font font = getFont(row, dataCol); 290 291 if (col != dataCol) 293 { 294 addAdditionalLines(row, col, dataItem); 295 dataSizes[row][dataCol] = new Dimension2DImpl(); } 297 else 298 dataSizes[row][dataCol] = new Dimension2DImpl(); 299 300 if (dataItem instanceof Boolean ) 301 { 302 dataSizes[row][col].addBelow(LayoutEngine.IMAGE_SIZE); 303 continue; 304 } 305 if (m_columnMaxWidth[col] == 0 || m_columnMaxWidth[col] == -1) 307 { 308 TextLayout layout = new TextLayout (string, font, frc); 309 float width = layout.getAdvance() + 2; float height = layout.getAscent() + layout.getDescent() + layout.getLeading(); 311 if (width > dynMxColumnWidth) 312 m_columnMaxWidth[col] = (int)Math.ceil(dynMxColumnWidth); 313 else if (colWidth < width) 314 colWidth = width; 315 dataSizes[row][col].addBelow(width, height); 316 } 317 if (m_columnMaxWidth[col] != 0 && m_columnMaxWidth[col] != -1) 319 { 320 float height = 0; 321 if (m_fixedWidth[col]) 322 colWidth = Math.abs(m_columnMaxWidth[col]); 323 String [] lines = Pattern.compile("$", Pattern.MULTILINE).split(string); 325 for (int lineNo = 0; lineNo < lines.length; lineNo++) 326 { 327 AttributedString aString = new AttributedString(lines[lineNo]); 328 aString.addAttribute(TextAttribute.FONT, font); 329 AttributedCharacterIterator iter = aString.getIterator(); 330 LineBreakMeasurer measurer = new LineBreakMeasurer(iter, frc); 331 while (measurer.getPosition() < iter.getEndIndex()) 332 { 333 TextLayout layout = measurer.nextLayout(Math.abs(m_columnMaxWidth[col])); 334 float width = layout.getAdvance(); 335 if (colWidth < width) 336 colWidth = width; 337 float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading(); 338 if (m_columnMaxHeight[col] == -1) { 340 height = lineHeight; 341 break; 342 } 343 else if (m_columnMaxHeight[col] == 0 || (height + lineHeight) <= m_columnMaxHeight[col]) 344 height += lineHeight; 345 } 346 } dataSizes[row][col].addBelow(colWidth, height); 348 } 349 dataSizes[row][col].roundUp(); 350 if (dataItem instanceof NamePair) 351 m_rowColDrillDown.put(new Point(row, col), dataItem); 352 } 355 String string = ""; 357 if (m_columnHeader[dataCol] != null) 358 string = m_columnHeader[dataCol].toString(); 359 360 if (col != dataCol) 362 headerSizes[dataCol] = new Dimension2DImpl(); 363 else if (colWidth == 0 && m_columnMaxWidth[dataCol] < 0 || string.length() == 0) 365 headerSizes[dataCol] = new Dimension2DImpl(); 366 else 367 { 368 Font font = getFont(HEADER_ROW, dataCol); 369 if (!font.isBold()) 370 font = new Font(font.getName(), Font.BOLD, font.getSize()); 371 if (m_columnMaxWidth[dataCol] == 0 || m_columnMaxWidth[dataCol] == -1 || !m_multiLineHeader) 373 { 374 TextLayout layout = new TextLayout (string, font, frc); 375 float width = layout.getAdvance() + 3; float height = layout.getAscent() + layout.getDescent() + layout.getLeading(); 377 if (width > dynMxColumnWidth) 378 m_columnMaxWidth[dataCol] = (int)Math.ceil(dynMxColumnWidth); 379 else if (colWidth < width) 380 colWidth = width; 381 headerSizes[dataCol] = new Dimension2DImpl(width, height); 382 } 383 if (m_columnMaxWidth[dataCol] != 0 && m_columnMaxWidth[dataCol] != -1) 385 { 386 float height = 0; 387 String [] lines = Pattern.compile("$", Pattern.MULTILINE).split(string); 389 for (int lineNo = 0; lineNo < lines.length; lineNo++) 390 { 391 AttributedString aString = new AttributedString(lines[lineNo]); 392 aString.addAttribute(TextAttribute.FONT, font); 393 AttributedCharacterIterator iter = aString.getIterator(); 394 LineBreakMeasurer measurer = new LineBreakMeasurer(iter, frc); 395 colWidth = Math.abs(m_columnMaxWidth[dataCol]); 396 while (measurer.getPosition() < iter.getEndIndex()) 397 { 398 TextLayout layout = measurer.nextLayout(colWidth); 399 float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading(); 400 if (!m_multiLineHeader) { 402 height = lineHeight; 403 break; 404 } 405 else if (m_columnMaxHeight[dataCol] == 0 406 || (height + lineHeight) <= m_columnMaxHeight[dataCol]) 407 height += lineHeight; 408 } 409 } headerSizes[dataCol] = new Dimension2DImpl(colWidth, height); 411 } 412 413 } headerSizes[dataCol].roundUp(); 415 colWidth = (float)Math.ceil(colWidth); 416 418 if (dataCol == 0) 420 colWidth += V_LINE; 421 if (colWidth != 0) 422 colWidth += (2*H_GAP) + V_LINE; 423 424 if (col != dataCol) 426 { 427 m_columnWidths.add(new Float (0.0)); Float origWidth = (Float )m_columnWidths.get(col); 429 if (origWidth == null) 430 Log.error("TableElement.calculateSize - Column " + dataCol + " below " + col + " - no value for orig width"); 431 else 432 { 433 if (origWidth.compareTo(new Float (colWidth)) >= 0) 434 Log.trace(Log.l6_Database, "TableElement.calculateSize - Same Width", 435 "Col=" + col + " - OrigWidth=" + origWidth + " - Width=" + colWidth + " - Total=" + p_width); 436 else 437 { 438 m_columnWidths.set(col, new Float (colWidth)); 439 p_width += (colWidth - origWidth.floatValue()); 440 Log.trace(Log.l6_Database, "TableElement.calculateSize - New Width", 441 "Col=" + col + " - OrigWidth=" + origWidth + " - Width=" + colWidth + " - Total=" + p_width); 442 } 443 } 444 } 445 else 447 { 448 m_columnWidths.add(new Float (colWidth)); 449 p_width += colWidth; 450 Log.trace(Log.l6_Database, "TableElement.calculateSize - Width", 451 "Col=" + dataCol + " - Width=" + colWidth + " - Total=" + p_width); 452 } 453 } 455 p_height = 0; 457 for (int row = 0; row < rows; row++) 458 { 459 float rowHeight = 0f; 460 for (int col = 0; col < cols; col++) 461 { 462 if (dataSizes[row][col].height > rowHeight) 463 rowHeight = (float)dataSizes[row][col].height; 464 } rowHeight += H_LINE + (2*V_GAP); 466 m_rowHeights.add(new Float (rowHeight)); 467 p_height += rowHeight; 468 } m_headerHeight = 0; 471 for (int col = 0; col < cols; col++) 472 { 473 if (headerSizes[col].height > m_headerHeight) 474 m_headerHeight = (int)headerSizes[col].height; 475 } m_headerHeight += (4*H_LINE) + (2*V_GAP); p_height += m_headerHeight; 478 479 480 482 Log.trace(Log.l5_DData, "TableElement.calculateSize", 483 "FirstPage=" + m_firstPage + ", NextPages=" + m_nextPages); 484 if (m_firstPage.height >= p_height && m_pageBreak.size() == 0) 486 { 487 Log.trace(Log.l6_Database, 488 "Page Y=1 - PageHeight=" + m_firstPage.height + " - TableHeight=" + p_height); 489 m_firstRowOnPage.add(new Integer (0)); m_pageHeight.add(new Float (p_height)); } 492 else 494 { 495 float availableHeight = 0f; 496 float usedHeight = 0f; 497 boolean firstPage = true; 498 for (int row = 0; row < m_rowHeights.size(); row++) 500 { 501 float rowHeight = ((Float )m_rowHeights.get(row)).floatValue(); 502 boolean forcePageBreak = isPageBreak(row); 504 if (availableHeight < rowHeight || forcePageBreak) 505 { 506 availableHeight = firstPage ? m_firstPage.height : m_nextPages.height; 507 m_firstRowOnPage.add(new Integer (row)); Log.trace(Log.l6_Database, "Page Y=" + m_firstRowOnPage.size(), "Row=" + row + " - force=" + forcePageBreak); 509 if (!firstPage) 510 { 511 m_pageHeight.add(new Float (usedHeight)); Log.trace(Log.l6_Database, "Page Y=" + m_pageHeight.size(), "PageHeight=" + usedHeight); 513 } 514 firstPage = false; 515 availableHeight -= m_headerHeight; 517 usedHeight += m_headerHeight; 518 } 519 availableHeight -= rowHeight; 520 usedHeight += rowHeight; 521 } m_pageHeight.add(new Float (usedHeight)); Log.trace(Log.l6_Database, "Page Y=" + m_pageHeight.size(), "PageHeight=" + usedHeight); 524 } 526 if (m_firstPage.width >= p_width) 528 { 529 Log.trace(Log.l6_Database, 530 "Page X=1 - PageWidth=" + m_firstPage.width + " - TableWidth=" + p_width); 531 m_firstColumnOnPage.add(new Integer (0)); distributeColumns (m_firstPage.width-(int)p_width, 0, m_columnWidths.size()); 534 } 535 else 537 { 538 int availableWidth = 0; 539 int lastStart = 0; 540 for (int col = 0; col < m_columnWidths.size(); col++) 541 { 542 int columnWidth = ((Float )m_columnWidths.get(col)).intValue(); 543 if (availableWidth < columnWidth) 545 { 546 if (col != 0) 547 distributeColumns (availableWidth, lastStart, col); 548 m_firstColumnOnPage.add(new Integer (col)); Log.trace(Log.l6_Database, 551 "Page X=" + m_firstColumnOnPage.size(), "Col=" + col); 552 lastStart = col; 553 availableWidth = m_firstPage.width; for (int repCol = 0; repCol < m_repeatedColumns && col > repCol; repCol++) 556 { 557 float repColumnWidth = ((Float )m_columnWidths.get(repCol)).floatValue(); 558 if (availableWidth < m_firstPage.width * 0.5) 560 break; 561 availableWidth -= repColumnWidth; 562 } 563 } availableWidth -= columnWidth; 565 } } 568 p_height += H_LINE; if (m_lastLineFunction) 571 p_height += H_LINE; 573 Log.trace(Log.l4_Data, "TableElement.calculateSize", 574 "Pages=" + getPageCount() + " X=" + m_firstColumnOnPage.size() + "/Y=" + m_firstRowOnPage.size() 575 + " - Width=" + p_width + ", Height=" + p_height); 576 return true; 577 } 579 580 586 private void distributeColumns (int availableWidth, int fromCol, int toCol) 587 { 588 Log.trace(8, "TableElement.distributeColumns", "Available=" + availableWidth + ", Columns " + fromCol + "->" + toCol); 589 int start = fromCol; 590 if (fromCol == 0 && m_repeatedColumns > 0) 591 start = m_repeatedColumns; 592 int totalWidth = availableWidth; 594 for (int col = start; col < toCol; col++) 595 totalWidth += ((Float )m_columnWidths.get(col)).floatValue(); 596 int remainingWidth = availableWidth; 597 for (int x = 0; remainingWidth > 0 && x < 5; x++) { 600 Log.trace(9, "TotalWidth=" + totalWidth + ", Remaining=" + remainingWidth); 601 for (int col = start; col < toCol && remainingWidth != 0; col++) 602 { 603 int columnWidth = ((Float )m_columnWidths.get(col)).intValue(); 604 if (columnWidth != 0) 605 { 606 int additionalPart = columnWidth * availableWidth / totalWidth; 607 if (remainingWidth < additionalPart) 608 { 609 m_columnWidths.set(col, new Float (columnWidth+remainingWidth)); 610 remainingWidth = 0; 611 } 612 else 613 { 614 m_columnWidths.set(col, new Float (columnWidth+additionalPart)); 615 remainingWidth -= additionalPart; 616 } 617 Log.trace(9, "Column " + col, "From " + columnWidth + " to " + m_columnWidths.get(col)); 618 } 619 } 620 } 621 for (int c = toCol-1; remainingWidth != 0 && c >=0; c--) 623 { 624 int columnWidth = ((Float )m_columnWidths.get(c)).intValue(); 625 if (columnWidth > 0) 626 { 627 m_columnWidths.set(c, new Float (columnWidth+remainingWidth)); 628 Log.trace(9, "Final Column " + c, "From " + columnWidth + " to " + m_columnWidths.get(c)); 629 remainingWidth = 0; 630 } 631 } 632 } 634 639 private boolean isPageBreak (int row) 640 { 641 for (int i = 0; i < m_pageBreak.size(); i++) 642 { 643 Integer rr = (Integer )m_pageBreak.get(i); 644 if (rr.intValue()+1 == row) 645 return true; 646 else if (rr.intValue() > row) 647 return false; 648 } 649 return false; 650 } 652 655 public void setHeightToLastPage() 656 { 657 p_height = getHeight(getPageCount()); 658 Log.trace(Log.l5_DData, "TableElement.setHeightToLastPage (" + getPageCount() + ")", String.valueOf(p_height)); 659 } 661 662 663 681 private Font getFont (int row, int col) 682 { 683 Font font = (Font)m_rowColFont.get(new Point(row, col)); 685 if (font != null) 686 return font; 687 font = (Font)m_rowColFont.get(new Point (row, ALL)); 689 if (font != null) 690 return font; 691 font = (Font)m_rowColFont.get(new Point (ALL, col)); 693 if (font != null) 694 return font; 695 return m_baseFont; 697 } 699 705 private Color getColor (int row, int col) 706 { 707 Color color = (Color)m_rowColColor.get(new Point(row, col)); 709 if (color != null) 710 return color; 711 color = (Color)m_rowColColor.get(new Point (row, ALL)); 713 if (color != null) 714 return color; 715 color = (Color)m_rowColColor.get(new Point (ALL, col)); 717 if (color != null) 718 return color; 719 return m_baseColor; 721 } 723 729 private Color getBackground (int row, int col) 730 { 731 Color color = (Color)m_rowColBackground.get(new Point(row, col)); 733 if (color != null) 734 return color; 735 color = (Color)m_rowColBackground.get(new Point (row, ALL)); 737 if (color != null) 738 return color; 739 color = (Color)m_rowColBackground.get(new Point (ALL, col)); 741 if (color != null) 742 return color; 743 return m_baseBackground; 745 } 747 748 749 754 public float getHeight (int pageNo) 755 { 756 int pageIndex = getPageIndex(pageNo); 757 int pageYindex = getPageYIndex(pageIndex); 758 float pageHeight = ((Float )m_pageHeight.get(pageYindex)).floatValue(); 759 float pageHeightPrevious = 0f; 760 if (pageYindex > 0) 761 pageHeightPrevious = ((Float )m_pageHeight.get(pageYindex-1)).floatValue(); 762 float retValue = pageHeight - pageHeightPrevious; 763 Log.trace(Log.l6_Database, "TableElement.getHeight (" + pageNo + ")", 764 "PageIndex=" + pageIndex + ", PageYindex=" + pageYindex + ", Height=" + String.valueOf(retValue)); 765 return retValue; 766 } 768 773 public float getWidth (int pageNo) 774 { 775 int pageIndex = getPageIndex(pageNo); 776 if (pageIndex == 0) 777 return m_firstPage.width; 778 return m_nextPages.width; 779 } 781 782 783 787 public int getPageCount() 788 { 789 return m_firstRowOnPage.size() * m_firstColumnOnPage.size(); 790 } 792 797 protected int getPageIndex (int pageNo) 798 { 799 return pageNo - m_pageNoStart; 800 } 802 807 private int getPageNo (int pageIndex) 808 { 809 return m_pageNoStart + pageIndex; 810 } 812 813 814 834 protected int getPageXIndex (int pageIndex) 835 { 836 int noXpages = m_firstColumnOnPage.size(); 837 int x = pageIndex % noXpages; 839 return x; 840 } 842 846 protected int getPageXCount () 847 { 848 return m_firstColumnOnPage.size(); 849 } 851 871 protected int getPageYIndex (int pageIndex) 872 { 873 int noXpages = m_firstColumnOnPage.size(); 874 int y = (pageIndex - (pageIndex % noXpages)) / noXpages; 876 return y; 877 } 879 883 protected int getPageYCount () 884 { 885 return m_firstRowOnPage.size(); 886 } 888 889 890 896 public MQuery getDrillDown (Point relativePoint, int pageNo) 897 { 898 if (m_rowColDrillDown.size() == 0) 899 return null; 900 if (!getBounds(pageNo).contains(relativePoint)) 901 return null; 902 int row = getRow (relativePoint.y, pageNo); 903 if (row == -1) 904 return null; 905 int col = getCol (relativePoint.x, pageNo); 906 if (col == -1) 907 return null; 908 Log.trace(Log.l5_DData, "TableElement.getDrillDown", "Row=" + row + ", Col=" + col + ", PageNo=" + pageNo); 909 NamePair pp = (NamePair)m_rowColDrillDown.get(new Point(row,col)); 911 if (pp == null) 912 return null; 913 String columnName = m_columnHeader[col].getID(); 914 String tableName = columnName; 915 int index = tableName.lastIndexOf("_ID"); 916 if (index != -1) 917 tableName = tableName.substring(0, index); 918 Object code = pp.getID(); 919 if (pp instanceof KeyNamePair) 920 code = new Integer (((KeyNamePair)pp).getKey()); 921 MQuery query = new MQuery(tableName); 923 query.addRestriction(columnName, MQuery.EQUAL, code, null, pp.toString()); 924 return query; 925 } 927 933 public MQuery getDrillAcross (Point relativePoint, int pageNo) 934 { 935 if (!getBounds(pageNo).contains(relativePoint)) 936 return null; 937 int row = getRow (relativePoint.y, pageNo); 938 if (row == -1) 939 return null; 940 Log.trace(Log.l5_DData, "TableElement.getDrillAcross", "Row=" + row + ", PageNo=" + pageNo); 941 if (m_pk[row] == null) return null; 944 return MQuery.getEqualQuery(m_pkColumnName, m_pk[row].getKey()); 945 } 947 953 public Rectangle getBounds(int pageNo) 954 { 955 int pageIndex = getPageIndex(pageNo); 956 int pageYindex = getPageYIndex(pageIndex); 957 if (pageYindex == 0) 958 return m_firstPage; 959 else 960 return m_nextPages; 961 } 963 964 970 private int getRow (int yPos, int pageNo) 971 { 972 int pageIndex = getPageIndex(pageNo); 973 int pageYindex = getPageYIndex(pageIndex); 974 int curY = (pageYindex == 0 ? m_firstPage.y : m_nextPages.y) + m_headerHeight; 976 if (yPos < curY) 977 return -1; int firstRow = ((Integer )m_firstRowOnPage.get(pageYindex)).intValue(); 980 int nextPageRow = m_data.length; if (pageYindex+1 < m_firstRowOnPage.size()) 982 nextPageRow = ((Integer )m_firstRowOnPage.get(pageYindex+1)).intValue(); 983 for (int row = firstRow; row < nextPageRow; row++) 985 { 986 int rowHeight = ((Float )m_rowHeights.get(row)).intValue(); if (yPos >= curY && yPos < (curY + rowHeight)) 988 return row; 989 curY += rowHeight; 990 } 991 return -1; 993 } 995 1001 private int getCol (int xPos, int pageNo) 1002 { 1003 int pageIndex = getPageIndex(pageNo); 1004 int pageXindex = getPageXIndex(pageIndex); 1005 int curX = pageXindex == 0 ? m_firstPage.x : m_nextPages.x; 1007 if (xPos < curX) 1008 return -1; 1010 int firstColumn = ((Integer )m_firstColumnOnPage.get(pageXindex)).intValue(); 1011 int nextPageColumn = m_columnHeader.length; if (pageXindex+1 < m_firstColumnOnPage.size()) 1013 nextPageColumn = ((Integer )m_firstColumnOnPage.get(pageXindex+1)).intValue(); 1014 1015 int regularColumnStart = firstColumn; 1017 for (int col = 0; col < m_repeatedColumns; col++) 1018 { 1019 int colWidth = ((Float )m_columnWidths.get(col)).intValue(); if (xPos >= curX && xPos < (curX + colWidth)) 1021 return col; 1022 curX += colWidth; 1023 if (regularColumnStart == col) 1024 regularColumnStart++; 1025 } 1026 for (int col = regularColumnStart; col < nextPageColumn; col++) 1028 { 1029 int colWidth = ((Float )m_columnWidths.get(col)).intValue(); if (xPos >= curX && xPos < (curX + colWidth)) 1031 return col; 1032 curX += colWidth; 1033 } return -1; 1036 } 1038 1039 1040 1049 public void paint (Graphics2D g2D, int pageNo, Point2D pageStart, Properties ctx, boolean isView) 1050 { 1051 int pageIndex = getPageIndex(pageNo); 1052 int pageXindex = getPageXIndex(pageIndex); 1053 int pageYindex = getPageYIndex(pageIndex); 1054 int firstColumn = ((Integer )m_firstColumnOnPage.get(pageXindex)).intValue(); 1058 int nextPageColumn = m_columnHeader.length; if (pageXindex+1 < m_firstColumnOnPage.size()) 1060 nextPageColumn = ((Integer )m_firstColumnOnPage.get(pageXindex+1)).intValue(); 1061 int firstRow = ((Integer )m_firstRowOnPage.get(pageYindex)).intValue(); 1063 int nextPageRow = m_data.length; if (pageYindex+1 < m_firstRowOnPage.size()) 1065 nextPageRow = ((Integer )m_firstRowOnPage.get(pageYindex+1)).intValue(); 1066 1069 int startX = (int)pageStart.getX(); 1071 int startY = (int)pageStart.getY(); 1072 startX += pageXindex == 0 ? m_firstPage.x : m_nextPages.x; 1074 startY += pageYindex == 0 ? m_firstPage.y : m_nextPages.y; 1075 1077 boolean firstColumnPrint = true; 1079 int regularColumnStart = firstColumn; 1080 for (int col = 0; col < m_repeatedColumns && col < m_columnWidths.size(); col++) 1081 { 1082 int colWidth = ((Float )m_columnWidths.get(col)).intValue(); if (colWidth != 0) 1084 { 1085 printColumn (g2D, col, startX, startY, firstColumnPrint, firstRow, nextPageRow, isView); 1086 startX += colWidth; 1087 firstColumnPrint = false; 1088 } 1089 if (regularColumnStart == col) 1090 regularColumnStart++; 1091 } 1092 1093 for (int col = regularColumnStart; col < nextPageColumn; col++) 1095 { 1096 int colWidth = ((Float )m_columnWidths.get(col)).intValue(); if (colWidth != 0) 1098 { 1099 printColumn (g2D, col, startX, startY, firstColumnPrint, firstRow, nextPageRow, isView); 1100 startX += colWidth; 1101 firstColumnPrint = false; 1102 } 1103 } 1105 } 1107 1118 private void printColumn (Graphics2D g2D, int col, 1119 final int origX, final int origY, boolean leftVline, 1120 final int firstRow, final int nextPageRow, boolean isView) 1121 { 1122 int curX = origX; 1123 int curY = origY; int colWidth = ((Float )m_columnWidths.get(col)).intValue(); int netWidth = colWidth - (2*H_GAP) - V_LINE; 1127 if (leftVline) 1128 netWidth -= V_LINE; 1129 int rowHeight = m_headerHeight; 1130 int netHeight = rowHeight - (4*H_LINE) + (2*V_GAP); 1131 1132 String alignment = m_columnJustification[col]; 1135 1136 if (leftVline) { 1139 g2D.setPaint(m_tFormat.getVLine_Color()); 1140 g2D.setStroke(m_tFormat.getVLine_Stroke()); 1141 if (m_tFormat.isPaintBoundaryLines()) 1142 g2D.drawLine(origX, origY+H_LINE, origX, (origY+rowHeight-(4*H_LINE))); curX += V_LINE; 1144 } 1145 g2D.setPaint(m_tFormat.getHeaderLine_Color()); 1147 g2D.setStroke(m_tFormat.getHeader_Stroke()); 1148 g2D.drawLine(origX, origY, (origX+colWidth-V_LINE), origY); curY += (2 * H_LINE); Color bg = getBackground(HEADER_ROW, col); 1152 if (!bg.equals(Color.white)) 1153 { 1154 g2D.setPaint(bg); 1155 g2D.fillRect(curX, curY-H_LINE, colWidth-V_LINE, rowHeight-(4*H_LINE)); 1156 } 1157 curX += H_GAP; curY += V_GAP; 1159 AttributedString aString = null; 1161 AttributedCharacterIterator iter = null; 1162 LineBreakMeasurer measurer = null; 1163 float usedHeight = 0; 1164 if (m_columnHeader[col].toString().length() > 0) 1165 { 1166 aString = new AttributedString(m_columnHeader[col].toString()); 1167 Font font = getFont(HEADER_ROW, col); 1168 aString.addAttribute(TextAttribute.FONT, font); 1169 aString.addAttribute(TextAttribute.FOREGROUND, getColor(HEADER_ROW, col)); 1170 iter = aString.getIterator(); 1171 measurer = new LineBreakMeasurer(iter, g2D.getFontRenderContext()); 1172 while (measurer.getPosition() < iter.getEndIndex()) { 1174 TextLayout layout = measurer.nextLayout(netWidth + 2); 1175 float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading(); 1176 if (m_columnMaxHeight[col] == 0 || (usedHeight + lineHeight) <= m_columnMaxHeight[col]) 1177 { 1178 if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Block)) 1179 layout = layout.getJustifiedLayout(netWidth + 2); 1180 curY += layout.getAscent(); 1181 float penX = curX; 1182 if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Center)) 1183 penX += (netWidth-layout.getAdvance())/2; 1184 else if ((alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_TrailingRight) && layout.isLeftToRight()) 1185 || (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_LeadingLeft) && !layout.isLeftToRight())) 1186 penX += netWidth-layout.getAdvance(); 1187 layout.draw(g2D, penX, curY); curY += layout.getDescent() + layout.getLeading(); 1189 usedHeight += lineHeight; 1190 } 1191 if (!m_multiLineHeader) break; 1193 } 1194 } curX += netWidth + H_GAP; 1196 curY += V_GAP; 1197 g2D.setPaint(m_tFormat.getVLine_Color()); 1199 g2D.setStroke(m_tFormat.getVLine_Stroke()); 1200 if (m_tFormat.isPaintVLines()) 1201 g2D.drawLine(curX, origY+H_LINE, curX, (origY+rowHeight-(4*H_LINE))); curX += V_LINE; 1203 g2D.setPaint(m_tFormat.getHeaderLine_Color()); 1205 g2D.setStroke(m_tFormat.getHeader_Stroke()); 1206 g2D.drawLine(origX, curY, (origX+colWidth-V_LINE), curY); curY += (2 * H_LINE); 1209 1210 for (int row = firstRow; row < nextPageRow; row++) 1212 { 1213 rowHeight = ((Float )m_rowHeights.get(row)).intValue(); netHeight = rowHeight - (2*V_GAP) - H_LINE; 1215 int rowYstart = curY; 1216 1217 curX = origX; 1218 if (leftVline) { 1220 g2D.setPaint(m_tFormat.getVLine_Color()); 1221 g2D.setStroke(m_tFormat.getVLine_Stroke()); 1222 if (m_tFormat.isPaintBoundaryLines()) 1223 g2D.drawLine(curX, rowYstart, curX, (rowYstart+rowHeight-H_LINE)); curX += V_LINE; 1225 } 1226 bg = getBackground(row, col); 1228 if (!bg.equals(Color.white)) 1229 { 1230 g2D.setPaint(bg); 1231 g2D.fillRect(curX, curY, colWidth-V_LINE, rowHeight-H_LINE); 1232 } 1233 curX += H_GAP; curY += V_GAP; 1235 1236 Object [] printItems = getPrintItems(row,col); 1238 float penY = curY; 1239 for (int index = 0; index < printItems.length; index++) 1240 { 1241 if (printItems[index] == null) 1242 ; 1243 else if (printItems[index] instanceof Boolean ) 1244 { 1245 int penX = curX + (netWidth-LayoutEngine.IMAGE_SIZE.width)/2; if (((Boolean )printItems[index]).booleanValue()) 1247 g2D.drawImage(LayoutEngine.IMAGE_TRUE, penX, (int)penY, this); 1248 else 1249 g2D.drawImage(LayoutEngine.IMAGE_FALSE, penX, (int)penY, this); 1250 penY += LayoutEngine.IMAGE_SIZE.height; 1251 } 1252 else 1253 { 1254 String str = printItems[index].toString(); 1255 if (str.length() > 0) 1256 { 1257 usedHeight = 0; 1258 String [] lines = Pattern.compile("$", Pattern.MULTILINE).split(str); 1259 for (int lineNo = 0; lineNo < lines.length; lineNo++) 1260 { 1261 aString = new AttributedString(lines[lineNo]); 1262 aString.addAttribute(TextAttribute.FONT, getFont(row, col)); 1263 if (isView && printItems[index] instanceof NamePair) { 1265 aString.addAttribute(TextAttribute.FOREGROUND, LINK_COLOR); 1266 aString.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL, 0, str.length()); 1267 } 1268 else 1269 aString.addAttribute(TextAttribute.FOREGROUND, getColor(row, col)); 1270 iter = aString.getIterator(); 1271 measurer = new LineBreakMeasurer(iter, g2D.getFontRenderContext()); 1272 while (measurer.getPosition() < iter.getEndIndex()) { 1274 TextLayout layout = measurer.nextLayout(netWidth + 2); 1275 float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading(); 1276 if ((m_columnMaxHeight[col] == 0 || (usedHeight + lineHeight) <= m_columnMaxHeight[col]) 1277 && (usedHeight + lineHeight) <= netHeight) 1278 { 1279 if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Block) && measurer.getPosition() < iter.getEndIndex()) 1280 layout = layout.getJustifiedLayout(netWidth + 2); 1281 penY += layout.getAscent(); 1282 float penX = curX; 1283 if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Center)) 1284 penX += (netWidth-layout.getAdvance())/2; 1285 else if ((alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_TrailingRight) && layout.isLeftToRight()) 1286 || (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_LeadingLeft) && !layout.isLeftToRight())) 1287 penX += netWidth-layout.getAdvance(); 1288 layout.draw(g2D, penX, penY); penY += layout.getDescent() + layout.getLeading(); 1290 usedHeight += lineHeight; 1291 } 1292 } } } } } 1298 curY += netHeight + V_GAP; 1299 curX += netWidth + H_GAP; 1300 g2D.setPaint(m_tFormat.getVLine_Color()); 1302 g2D.setStroke(m_tFormat.getVLine_Stroke()); 1303 if (m_tFormat.isPaintVLines()) 1304 g2D.drawLine(curX, rowYstart, curX, (rowYstart+rowHeight-H_LINE)); curX += V_LINE; 1306 1307 if (row == m_data.length-1 || (row == m_data.length-2 && m_lastLineFunction)) 1310 { 1311 g2D.setPaint(m_tFormat.getHeaderLine_Color()); 1312 g2D.setStroke(m_tFormat.getHeader_Stroke()); 1313 g2D.drawLine(origX, curY, (origX+colWidth-V_LINE), curY); curY += (2 * H_LINE); } 1316 else 1317 { 1318 g2D.setPaint(m_tFormat.getHLine_Color()); 1319 g2D.setStroke(m_tFormat.getHLine_Stroke()); 1320 if (m_tFormat.isPaintHLines()) 1321 g2D.drawLine(origX, curY, (origX+colWidth-V_LINE), curY); curY += H_LINE; 1323 } 1324 } } 1327 1333 private void addAdditionalLines (int row, int col, Object data) 1334 { 1335 Point key = new Point (row,col); 1336 ArrayList list = (ArrayList)m_additionalLineData.get(key); 1337 if (list == null) 1338 list = new ArrayList(); 1339 list.add(data); 1340 m_additionalLineData.put(key, list); 1341 } 1343 1349 private Object [] getPrintItems (int row, int col) 1350 { 1351 Point key = new Point (row,col); 1352 ArrayList list = (ArrayList)m_additionalLineData.get(key); 1353 if (list == null) 1354 { 1355 if (m_data[row][col] != null) 1356 return new Object [] {m_data[row][col]}; 1357 else 1358 return new Object [] {}; 1359 } 1360 ArrayList retList = new ArrayList(); 1362 retList.add(m_data[row][col]); 1363 retList.addAll(list); 1364 return retList.toArray(); 1365 } 1367} | Popular Tags |