/****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * * or via info@compiere.org or http://www.compiere.org/license.html * *****************************************************************************/ package org.compiere.print.layout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.io.Serializable; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Properties; import java.util.logging.Level; import java.util.regex.Pattern; import org.compiere.model.MQuery; import org.compiere.print.MPrintFormatItem; import org.compiere.print.MPrintTableFormat; import org.compiere.print.PrintData; import org.compiere.print.util.SerializableMatrix; import org.compiere.print.util.SerializableMatrixImpl; import org.compiere.report.MReportLine; import org.compiere.util.Evaluator; import org.compiere.util.KeyNamePair; import org.compiere.util.NamePair; import org.compiere.util.Util; import org.compiere.util.ValueNamePair; /** * Table Print Element. * Maintains a logical cross page table, which is "broken up" when printing *
* The table is 3 pages wide, 2 pages high * +-----+-----+-----+ * | 1.1 | 1.2 | 1.3 | * +-----+-----+-----+ * | 2.1 | 2.2 | 2.3 | * +-----+-----+-----+ * Printed * +-----+-----+-----+ * | 1 | 2 | 3 | * +-----+-----+-----+ * | 4 | 5 | 6 | * +-----+-----+-----+ ** @author Jorg Janke * @version $Id: TableElement.java,v 1.2 2006/07/30 00:53:02 jjanke Exp $ * * @author Teo Sarca, SC ARHIPAC SERVICE SRL *
* Examples: * From general to specific: * (-1,-1) => for entire table * (-1, c) => for entire column c * (r, -1) => for entire row r (overwrites column) * (r, c) => for specific cell (highest priority) * Header is row -2 * (-2,-1) => for all header columns * (-2, c) => for header column c ** @param row row * @param col column * @return Font for row/col */ private Font getFont (int row, int col) { // First specific position Font font = (Font)m_rowColFont.get(new Point(row, col)); if (font != null) return font; // Row Next font = (Font)m_rowColFont.get(new Point (row, ALL)); if (font != null) return font; // Column then font = (Font)m_rowColFont.get(new Point (ALL, col)); if (font != null) return font; // default return m_baseFont; } // getFont /** * Get Foreground Color. * @param row row * @param col column * @return Color for row/col */ private Color getColor (int row, int col) { // First specific position Color color = (Color)m_rowColColor.get(new Point(row, col)); if (color != null) return color; // Row Next color = (Color)m_rowColColor.get(new Point (row, ALL)); if (color != null) return color; // Column then color = (Color)m_rowColColor.get(new Point (ALL, col)); if (color != null) return color; // default return m_baseColor; } // getFont /** * Get Foreground Color. * @param row row * @param col column * @return Color for row/col */ private Color getBackground (int row, int col) { // First specific position Color color = (Color)m_rowColBackground.get(new Point(row, col)); if (color != null) return color; // Row Next color = (Color)m_rowColBackground.get(new Point (row, ALL)); if (color != null) return color; // Column then color = (Color)m_rowColBackground.get(new Point (ALL, col)); if (color != null) return color; // default return m_baseBackground; } // getFont /************************************************************************** * Get Calculated Height on page * @param pageNo layout page number * @return Height */ public float getHeight (int pageNo) { int pageIndex = getPageIndex(pageNo); int pageYindex = getPageYIndex(pageIndex); if (log.isLoggable(Level.FINE)) log.fine("Page=" + pageNo + " - PageIndex=" + pageIndex + ", PageYindex=" + pageYindex); float pageHeight = ((Float)m_pageHeight.get(pageYindex)).floatValue(); float pageHeightPrevious = 0f; if (pageYindex > 0) pageHeightPrevious = ((Float)m_pageHeight.get(pageYindex-1)).floatValue(); float retValue = pageHeight - pageHeightPrevious; if (log.isLoggable(Level.FINE)) log.fine("Page=" + pageNo + " - PageIndex=" + pageIndex + ", PageYindex=" + pageYindex + ", Height=" + String.valueOf(retValue)); return retValue; } // getHeight /** * Get Calculated Height on page * @param pageNo page number * @return Height */ public float getWidth (int pageNo) { int pageIndex = getPageIndex(pageNo); if (pageIndex == 0) return m_firstPage.width; return m_nextPages.width; } // getHeight /************************************************************************** * Get number of "real" pages. * @return page count */ public int getPageCount() { return m_firstRowOnPage.size() * m_firstColumnOnPage.size(); } // getPageCount /** * Get zero based Page Index within Layout * @param pageNo real page no * @return page index */ protected int getPageIndex (int pageNo) { int index = pageNo - m_pageNoStart; if (index < 0) log.log(Level.SEVERE, "index=" + index, new Exception()); return index; } // getPageIndex /** * Get "real" page Number within Layout * @param pageIndex zero based page index * @return page number */ /*private int getPageNo (int pageIndex) { return pageIndex + m_pageNoStart; } // getPageNo*/ /************************************************************************** * Get X - Page Index. * Zero Based; Page No is the "real" page No *
* The table is 3 pages wide, 2 pages high - index * +-----+-----+-----+ * | 0.0 | 0.1 | 0.2 | * +-----+-----+-----+ * | 1.0 | 1.1 | 1.2 | * +-----+-----+-----+ * Page Index * +-----+-----+-----+ * | 0 | 1 | 2 | * +-----+-----+-----+ * | 3 | 4 | 5 | * +-----+-----+-----+ ** @param pageIndex zero based page index * @return page index on X axis */ protected int getPageXIndex (int pageIndex) { int noXpages = m_firstColumnOnPage.size(); // int noYpages = m_firstRowOnPage.size(); int x = pageIndex % noXpages; return x; } // getPageXIndex /** * Get X - Page Count * @return X page count */ protected int getPageXCount () { return m_firstColumnOnPage.size(); } // getPageXCount /** * Get Y | Page Index. * Zero Based; Page No is the "real" page No *
* The table is 3 pages wide, 2 pages high - index * +-----+-----+-----+ * | 0.0 | 0.1 | 0.2 | * +-----+-----+-----+ * | 1.0 | 1.1 | 1.2 | * +-----+-----+-----+ * Page Index * +-----+-----+-----+ * | 0 | 1 | 2 | * +-----+-----+-----+ * | 3 | 4 | 5 | * +-----+-----+-----+ ** @param pageIndex zero based page index * @return page index on Y axis */ protected int getPageYIndex (int pageIndex) { int noXpages = m_firstColumnOnPage.size(); // int noYpages = m_firstRowOnPage.size(); int y = (pageIndex - (pageIndex % noXpages)) / noXpages; return y; } // getPageYIndex /** * Get Y | Page Count * @return Y page count */ protected int getPageYCount () { return m_firstRowOnPage.size(); } // getPageYCount /************************************************************************** * Get Drill Down value * @param relativePoint relative Point * @param pageNo page number * @return if found Qyery or null */ public MQuery getDrillDown (Point relativePoint, int pageNo) { if (m_rowColDrillDown.size() == 0) return null; if (!getBounds(pageNo).contains(relativePoint)) return null; int row = getRow (relativePoint.y, pageNo); if (row == -1) return null; int col = getCol (relativePoint.x, pageNo); if (col == -1) return null; if (log.isLoggable(Level.FINE)) log.fine("Row=" + row + ", Col=" + col + ", PageNo=" + pageNo); // NamePair pp = (NamePair)m_rowColDrillDown.get(new Point(row,col)); if (pp == null) return null; String columnName = MQuery.getZoomColumnName(m_columnHeader[col].getID()); String tableName = MQuery.getZoomTableName(columnName); Object code = pp.getID(); if (pp instanceof KeyNamePair) code = Integer.valueOf(((KeyNamePair)pp).getKey()); // MQuery query = new MQuery(tableName); query.addRestriction(columnName, MQuery.EQUAL, code, null, pp.toString()); return query; } // getDrillDown /** * Get Drill Across value * @param relativePoint relative Point * @param pageNo page number * @return if found Query or null */ public MQuery getDrillAcross (Point relativePoint, int pageNo) { if (!getBounds(pageNo).contains(relativePoint)) return null; int row = getRow (relativePoint.y, pageNo); if (row == -1) return null; if (log.isLoggable(Level.FINE)) log.fine("Row=" + row + ", PageNo=" + pageNo); // if (m_pk[row] == null) // FunctionRows return null; return MQuery.getEqualQuery(m_pkColumnName, m_pk[row].getKey()); } // getDrillAcross /** * Get relative Bounds of Element. * (entire page, not just used portion) * @param pageNo pageNo * @return bounds relative position on page */ public Rectangle getBounds(int pageNo) { int pageIndex = getPageIndex(pageNo); int pageYindex = getPageYIndex(pageIndex); if (pageYindex == 0) return m_firstPage; else return m_nextPages; } // getBounds /** * Get Row for yPos * @param yPos y position (page relative) * @param pageNo page number * @return row index or -1 */ private int getRow (int yPos, int pageNo) { int pageIndex = getPageIndex(pageNo); int pageYindex = getPageYIndex(pageIndex); // int curY = (pageYindex == 0 ? m_firstPage.y : m_nextPages.y) + m_headerHeight; if (yPos < curY) return -1; // above // int firstRow = ((Integer)m_firstRowOnPage.get(pageYindex)).intValue(); int nextPageRow = m_data.getRowCount(); // no of rows if (pageYindex+1 < m_firstRowOnPage.size()) nextPageRow = ((Integer)m_firstRowOnPage.get(pageYindex+1)).intValue(); // for (int row = firstRow; row < nextPageRow; row++) { int rowHeight = ((Float)m_rowHeights.get(row)).intValue(); // includes 2*Gaps+Line if (yPos >= curY && yPos < (curY + rowHeight)) return row; curY += rowHeight; } // below return -1; } // getRow /** * Get Column for xPos * @param xPos x position (page relative) * @param pageNo page number * @return column index or -1 */ private int getCol (int xPos, int pageNo) { int pageIndex = getPageIndex(pageNo); int pageXindex = getPageXIndex(pageIndex); // int curX = pageXindex == 0 ? m_firstPage.x : m_nextPages.x; if (xPos < curX) return -1; // too left int firstColumn = ((Integer)m_firstColumnOnPage.get(pageXindex)).intValue(); int nextPageColumn = m_columnHeader.length; // no of cols if (pageXindex+1 < m_firstColumnOnPage.size()) nextPageColumn = ((Integer)m_firstColumnOnPage.get(pageXindex+1)).intValue(); // fixed volumns int regularColumnStart = firstColumn; for (int col = 0; col < m_repeatedColumns; col++) { int colWidth = ((Float)m_columnWidths.get(col)).intValue(); // includes 2*Gaps+Line if (xPos >= curX && xPos < (curX + colWidth)) return col; curX += colWidth; if (regularColumnStart == col) regularColumnStart++; } // regular columns for (int col = regularColumnStart; col < nextPageColumn; col++) { int colWidth = ((Float)m_columnWidths.get(col)).intValue(); // includes 2*Gaps+Line if (xPos >= curX && xPos < (curX + colWidth)) return col; curX += colWidth; } // for all columns // too right return -1; } // getCol /************************************************************************** * Paint/Print. * * @param g2D Graphics * @param pageNo page number for multi page support (0 = header/footer) * @param pageStart top left Location of page * @param ctx context * @param isView true if online view (IDs are links) */ public void paint (Graphics2D g2D, int pageNo, Point2D pageStart, Properties ctx, boolean isView) { int pageIndex = getPageIndex(pageNo); int pageXindex = getPageXIndex(pageIndex); int pageYindex = getPageYIndex(pageIndex); if (DEBUG_PRINT) if (log.isLoggable(Level.CONFIG)) log.config("Page=" + pageNo + " [x=" + pageXindex + ", y=" + pageYindex + "]"); // int firstColumn = ((Integer)m_firstColumnOnPage.get(pageXindex)).intValue(); int nextPageColumn = m_columnHeader.length; // no of cols if (pageXindex+1 < m_firstColumnOnPage.size()) nextPageColumn = ((Integer)m_firstColumnOnPage.get(pageXindex+1)).intValue(); // if (pageYindex >= m_firstRowOnPage.size()) { pageYindex = m_firstRowOnPage.size() - 1; } if (pageYindex<0) return; int firstRow = ((Integer)m_firstRowOnPage.get(pageYindex)).intValue(); int nextPageRow = m_data.getRowCount(); // no of rows if (pageYindex+1 < m_firstRowOnPage.size()) nextPageRow = ((Integer)m_firstRowOnPage.get(pageYindex+1)).intValue(); if (DEBUG_PRINT) if (log.isLoggable(Level.FINEST)) log.finest("Col=" + firstColumn + "-" + (nextPageColumn-1) + ", Row=" + firstRow + "-" + (nextPageRow-1)); // Top Left int startX = (int)pageStart.getX(); int startY = (int)pageStart.getY(); // Table Start startX += pageIndex == 0 ? m_firstPage.x : m_nextPages.x; startY += pageIndex == 0 ? m_firstPage.y : m_nextPages.y; if (DEBUG_PRINT) if (log.isLoggable(Level.FINEST)) log.finest("PageStart=" + pageStart + ", StartTable x=" + startX + ", y=" + startY); // paint first fixed volumns boolean firstColumnPrint = true; int regularColumnStart = firstColumn; for (int col = 0; col < m_repeatedColumns && col < m_columnWidths.size(); col++) { int colWidth = ((Float)m_columnWidths.get(col)).intValue(); // includes 2*Gaps+Line if (colWidth != 0) { printColumn (g2D, col, startX, startY, firstColumnPrint, firstRow, nextPageRow, isView); startX += colWidth; firstColumnPrint = false; } if (regularColumnStart == col) regularColumnStart++; } // paint columns for (int col = regularColumnStart; col < nextPageColumn; col++) { int colWidth = ((Float)m_columnWidths.get(col)).intValue(); // includes 2*Gaps+Line if (colWidth != 0) { printColumn (g2D, col, startX, startY, firstColumnPrint, firstRow, nextPageRow, isView); startX += colWidth; firstColumnPrint = false; } } // for all columns } // paint /** * Print non zero width Column * @param g2D graphics * @param col column index * @param origX start X * @param origY start Y * @param leftVline if true print left vertical line (for first column) * @param firstRow first row index * @param nextPageRow row index of next page * @param isView true if online view (IDs are links) */ private void printColumn (Graphics2D g2D, int col, final int origX, final int origY, boolean leftVline, final int firstRow, final int nextPageRow, boolean isView) { int curX = origX; int curY = origY; // start from top // float colWidth = ((Float)m_columnWidths.get(col)).floatValue(); // includes 2*Gaps+Line float netWidth = colWidth - (2*H_GAP) - m_tFormat.getVLineStroke().floatValue(); if (leftVline) netWidth -= m_tFormat.getVLineStroke().floatValue(); float rowHeight = m_headerHeight; float netHeight = rowHeight - (4*m_tFormat.getLineStroke().floatValue()) + (2*V_GAP); if (DEBUG_PRINT) if (log.isLoggable(Level.FINER)) log.finer("#" + col + " - x=" + curX + ", y=" + curY + ", width=" + colWidth + "/" + netWidth + ", HeaderHeight=" + rowHeight + "/" + netHeight); String alignment = m_columnJustification[col]; // paint header *************************************************** if (leftVline) // draw left | line { g2D.setPaint(m_tFormat.getVLine_Color()); g2D.setStroke(m_tFormat.getVLine_Stroke()); if (m_tFormat.isPaintBoundaryLines()) // -> | (left) g2D.drawLine(origX, (int)(origY+m_tFormat.getLineStroke().floatValue()), origX, (int)(origY+rowHeight-(4*m_tFormat.getLineStroke().floatValue()))); curX += m_tFormat.getVLineStroke().floatValue(); } // X - start line if (m_tFormat.isPaintHeaderLines()) { g2D.setPaint(m_tFormat.getHeaderLine_Color()); g2D.setStroke(m_tFormat.getHeader_Stroke()); g2D.drawLine(origX, origY, // -> - (top) (int)(origX+colWidth-m_tFormat.getVLineStroke().floatValue()), origY); } curY += (2 * m_tFormat.getLineStroke().floatValue()); // thick // Background Color bg = getBackground(HEADER_ROW, col); if (!bg.equals(Color.white)) { g2D.setPaint(bg); g2D.fillRect(curX, (int)(curY-m_tFormat.getLineStroke().floatValue()), (int)(colWidth-m_tFormat.getVLineStroke().floatValue()), (int)(rowHeight-(4*m_tFormat.getLineStroke().floatValue()))); } int tempCurY = curY; curX += H_GAP; // upper left gap curY += V_GAP; // Header AttributedString aString = null; AttributedCharacterIterator iter = null; LineBreakMeasurer measurer = null; float usedHeight = 0; // Calculate column header height - teo_sarca [ 1673429 ] String headerString = m_columnHeader[col].toString(); if (headerString.length() == 0) headerString = " "; //if (m_columnHeader[col].toString().length() > 0) { aString = new AttributedString(headerString); aString.addAttribute(TextAttribute.FONT, getFont(HEADER_ROW, col)); aString.addAttribute(TextAttribute.FOREGROUND, getColor(HEADER_ROW, col)); // boolean fastDraw = LayoutEngine.s_FASTDRAW; if (fastDraw && !isView && !Util.is8Bit(headerString)) fastDraw = false; iter = aString.getIterator(); measurer = new LineBreakMeasurer(iter, g2D.getFontRenderContext()); while (measurer.getPosition() < iter.getEndIndex()) // print header { TextLayout layout = measurer.nextLayout(netWidth + 2); if (iter.getEndIndex() != measurer.getPosition()) fastDraw = false; //float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading(); if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Block)) { layout = layout.getJustifiedLayout(netWidth + 2); fastDraw = false; } curY += layout.getAscent(); float penX = curX; if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Center)) penX += (netWidth-layout.getAdvance())/2; else if ((alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_TrailingRight) && layout.isLeftToRight()) || (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_LeadingLeft) && !layout.isLeftToRight())) penX += netWidth-layout.getAdvance(); // if (fastDraw) { // Bug - set Font/Color explicitly g2D.setFont(getFont(HEADER_ROW, col)); g2D.setColor(getColor(HEADER_ROW, col)); g2D.drawString(iter, penX, curY); } else layout.draw(g2D, penX, curY); // -> text curY += layout.getDescent() + layout.getLeading(); usedHeight += layout.getAscent() + layout.getDescent(); if ( !m_multiLineHeader ) // one line only break; } } curX += netWidth + H_GAP; curY = tempCurY + (int)(rowHeight-(4*m_tFormat.getLineStroke().floatValue())); // Y end line g2D.setPaint(m_tFormat.getVLine_Color()); g2D.setStroke(m_tFormat.getVLine_Stroke()); if (m_tFormat.isPaintVLines()) // -> | (right) g2D.drawLine(curX, (int)(origY+m_tFormat.getLineStroke().floatValue()), curX, (int)(origY+rowHeight-(4*m_tFormat.getLineStroke().floatValue()))); curX += m_tFormat.getVLineStroke().floatValue(); // X end line if (m_tFormat.isPaintHeaderLines()) { g2D.setPaint(m_tFormat.getHeaderLine_Color()); g2D.setStroke(m_tFormat.getHeader_Stroke()); g2D.drawLine(origX, curY, // -> - (button) (int)(origX+colWidth-m_tFormat.getVLineStroke().floatValue()), curY); } curY += (2 * m_tFormat.getLineStroke().floatValue()); // thick // paint Data *************************************************** for (int row = firstRow; row < nextPageRow; row++) { rowHeight = m_rowHeights.get(row); // includes 2*Gaps+Line netHeight = rowHeight - (2*V_GAP) - m_tFormat.getLineStroke().floatValue(); int rowYstart = curY; curX = origX; if (leftVline) // draw left | line { g2D.setPaint(m_tFormat.getVLine_Color()); g2D.setStroke(m_tFormat.getVLine_Stroke()); if (m_tFormat.isPaintBoundaryLines()) g2D.drawLine(curX, rowYstart, // -> | (left) curX, (int)(rowYstart+rowHeight-m_tFormat.getLineStroke().floatValue())); curX += m_tFormat.getVLineStroke().floatValue(); } // Background bg = getBackground(row, col); if (!bg.equals(Color.white)) { g2D.setPaint(bg); g2D.fillRect(curX, curY, (int)(colWidth-m_tFormat.getVLineStroke().floatValue()), (int)(rowHeight-m_tFormat.getLineStroke().floatValue()) ); } // Over Line MReportLine rLine = getReportLine(row, col); if (rLine != null) { if (rLine.getOverline() > 1) { curY -= V_GAP + m_tFormat.getVLineStroke().floatValue(); g2D.setPaint(m_tFormat.getHeaderLine_Color()); g2D.setStroke(rLine.getOverlineStroke(m_tFormat.getVLineStroke())); g2D.drawLine(curX, (int) (curY + m_tFormat.getVLineStroke().floatValue()), (int) (curX + colWidth - m_tFormat.getVLineStroke().floatValue()), (int) (curY + m_tFormat.getVLineStroke().floatValue())); curY += V_GAP + m_tFormat.getVLineStroke().floatValue(); } if (rLine.getOverline() > 0) { g2D.setPaint(m_tFormat.getHeaderLine_Color()); g2D.setStroke(rLine.getOverlineStroke(m_tFormat.getVLineStroke())); g2D.drawLine(curX, curY, (int) (curX + colWidth - m_tFormat.getVLineStroke().floatValue()), curY); curY += m_tFormat.getVLineStroke().floatValue(); } } curX += H_GAP; // upper left gap curY += V_GAP; // actual data Object[] printItems = getPrintItems(row,col); float penY = curY; // suppress repeated values boolean suppress = false; if (m_colSuppressRepeats[col] && row > 0 && row != firstRow) { Object[] lastItems = {}; lastItems = getPrintItems(row-1, col); if (Arrays.equals(lastItems,printItems) ) suppress = true; } if (!suppress) { if (m_tablePrintData != null && m_pageLogics != null && col < m_pageLogics.size()) { String pageLogic = m_pageLogics.get(col); if (!Util.isEmpty(pageLogic, true)) { m_tablePrintData.setRowIndex(row); PrintDataEvaluatee evaluatee = new PrintDataEvaluatee(getCurrentPage(), m_tablePrintData); boolean display = Evaluator.evaluateLogic(evaluatee, pageLogic); if (!display) suppress = true; } } } if ( !suppress ) { for (int index = 0; index < printItems.length; index++) { if (printItems[index] == null ) ; else if (printItems[index] instanceof ImageElement) { Image imageToDraw = ((ImageElement)printItems[index]).getImage(); if (imageToDraw != null) // teo_sarca [ 1674706 ] { // Draw image using the scale factor - teo_sarca, [ 1673548 ] Image is not scaled in a report table cell double scale = ((ImageElement)printItems[index]).getScaleFactor(); if (scale != 1.0) { AffineTransform transform = new AffineTransform(); transform.translate(curX, penY); transform.scale(scale, scale); g2D.drawImage(imageToDraw, transform, this); } else { g2D.drawImage(imageToDraw, curX, (int)penY, this); } } } else if (printItems[index] instanceof BarcodeElement) { BarcodeElement barcodeElement = (BarcodeElement)printItems[index]; barcodeElement.paint(g2D, curX, (int)penY); } else if (printItems[index] instanceof Boolean) { int penX = curX + (int)((netWidth-LayoutEngine.IMAGE_SIZE.width)/2); // center if (((Boolean)printItems[index]).booleanValue()) g2D.drawImage(LayoutEngine.IMAGE_TRUE, penX, (int)penY, this); else g2D.drawImage(LayoutEngine.IMAGE_FALSE, penX, (int)penY, this); penY += LayoutEngine.IMAGE_SIZE.height; } else if (printItems[index] instanceof HTMLRenderer) { HTMLRenderer renderer = (HTMLRenderer)printItems[index]; Rectangle allocation = new Rectangle((int)colWidth, (int)netHeight); // log.finest( "printColumn HTML - " + allocation); g2D.translate(curX, penY); renderer.paint(g2D, allocation); g2D.translate(-curX, -penY); penY += allocation.getHeight(); } else { String str = printItems[index].toString(); if (DEBUG_PRINT) if (log.isLoggable(Level.FINE)) log.fine("row=" + row + ",col=" + col + " - " + str + " 8Bit=" + Util.is8Bit(str)); if (str.length() > 0) { usedHeight = 0; String[] lines = Pattern.compile("\n", Pattern.MULTILINE).split(str); for (int lineNo = 0; lineNo < lines.length; lineNo++) { String thisLine = lines[lineNo]; if (thisLine.length() == 0) thisLine = " "; aString = new AttributedString(thisLine); aString.addAttribute(TextAttribute.FONT, getFont(row, col)); if (isView && printItems[index] instanceof NamePair) // ID { aString.addAttribute(TextAttribute.FOREGROUND, LINK_COLOR); aString.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL, 0, str.length()); } else aString.addAttribute(TextAttribute.FOREGROUND, getColor(row, col)); // iter = aString.getIterator(); boolean fastDraw = LayoutEngine.s_FASTDRAW; if (fastDraw && !isView && !Util.is8Bit(thisLine)) fastDraw = false; measurer = new LineBreakMeasurer(iter, g2D.getFontRenderContext()); while (measurer.getPosition() < iter.getEndIndex()) // print element { TextLayout layout = measurer.nextLayout(netWidth + 2); if (iter.getEndIndex() != measurer.getPosition()) fastDraw = false; float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading(); if ((m_columnMaxHeight[col] <= 0 || (usedHeight + lineHeight) <= m_columnMaxHeight[col]) && (usedHeight + lineHeight) <= netHeight) { if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Block) && measurer.getPosition() < iter.getEndIndex()) { layout = layout.getJustifiedLayout(netWidth + 2); fastDraw = false; } penY += layout.getAscent(); float penX = curX; if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Center)) penX += (netWidth-layout.getAdvance())/2; else if ((alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_TrailingRight) && layout.isLeftToRight()) || (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_LeadingLeft) && !layout.isLeftToRight())) penX += netWidth-layout.getAdvance(); // if (fastDraw) { // Bug - set Font/Color explicitly g2D.setFont(getFont(row, col)); if (isView && printItems[index] instanceof NamePair) // ID { g2D.setColor(LINK_COLOR); // TextAttribute.UNDERLINE } else g2D.setColor(getColor(row, col)); g2D.drawString(iter, penX, penY); } else layout.draw(g2D, penX, penY); // -> text if (DEBUG_PRINT) if (log.isLoggable(Level.FINE)) log.fine("row=" + row + ",col=" + col + " - " + str + " - x=" + penX + ",y=" + penY); penY += layout.getDescent() + layout.getLeading(); usedHeight += lineHeight; // if (m_columnMaxHeight[col] == -1) // FirstLineOny break; } } // print element } // for all lines } // length > 0 } // non boolean } // for all print items } // not suppressed curY += netHeight + V_GAP; curX += netWidth + H_GAP; // Y end line g2D.setPaint(m_tFormat.getVLine_Color()); g2D.setStroke(m_tFormat.getVLine_Stroke()); if (m_tFormat.isPaintVLines()) g2D.drawLine(curX, rowYstart, // -> | (right) curX, (int)(rowYstart+rowHeight-m_tFormat.getLineStroke().floatValue())); curX += m_tFormat.getVLineStroke().floatValue(); // Under Line if (rLine != null && rLine.getUnderline() > 0) { if (rLine.getUnderline() > 1) { curY -= V_GAP + m_tFormat.getVLineStroke().floatValue(); g2D.setPaint(m_tFormat.getHeaderLine_Color()); g2D.setStroke(rLine.getUnderlineStroke(m_tFormat.getVLineStroke())); g2D.drawLine(origX, curY, (int) (origX + colWidth - m_tFormat.getVLineStroke().floatValue()), curY); curY += V_GAP + m_tFormat.getVLineStroke().floatValue(); } if (rLine.getUnderline() > 0) { g2D.setPaint(m_tFormat.getHeaderLine_Color()); g2D.setStroke(rLine.getUnderlineStroke(m_tFormat.getVLineStroke())); g2D.drawLine(origX, curY, (int) (origX + colWidth - m_tFormat.getVLineStroke().floatValue()), curY); } } // Maintain financial report detail and column section Y position if ((int) (rowYstart + rowHeight) > curY) { curY = (int) (rowYstart + rowHeight); } // X end line if (row == m_data.getRowCount()-1) // last Line { // left some space between underline and last line curY += 2 * V_GAP; /** * Bug fix - Bottom line was always displayed whether or not header lines was set to be visible * @author ashley */ if (m_tFormat.isPaintHeaderLines()) { g2D.setPaint(m_tFormat.getHeaderLine_Color()); g2D.setStroke(m_tFormat.getHeader_Stroke()); g2D.drawLine(origX, curY, // -> - (last line) (int)(origX+colWidth-m_tFormat.getVLineStroke().floatValue()), curY); curY += (2 * m_tFormat.getLineStroke().floatValue()); // thick } else { curY += m_tFormat.getLineStroke().floatValue(); } } else { // next line is a function column -> underline this boolean nextIsFunction = m_functionRows.contains(Integer.valueOf(row+1)); if (nextIsFunction && m_functionRows.contains(Integer.valueOf(row))) nextIsFunction = false; // this is a function line too MReportLine nextLine = getReportLine(row + 1, col); if (nextIsFunction || (m_finReportSumRows.contains(Integer.valueOf(row + 1)) && nextLine != null && nextLine.getOverline() == 0)) { g2D.setPaint(m_tFormat.getFunctFG_Color()); g2D.setStroke(m_tFormat.getHLine_Stroke()); g2D.drawLine(origX, curY, // -> - (bottom) (int) (origX + colWidth - m_tFormat.getVLineStroke().floatValue()), curY); } else if (m_tFormat.isPaintHLines()) { g2D.setPaint(m_tFormat.getHLine_Color()); g2D.setStroke(m_tFormat.getHLine_Stroke()); g2D.drawLine(origX, curY, // -> - (bottom) (int)(origX+colWidth-m_tFormat.getVLineStroke().floatValue()), curY); } curY += m_tFormat.getLineStroke().floatValue(); } } // for all rows } // printColumn /** * Add Additional Lines to row/col * @param row row * @param col col * @param data data */ private void addPrintLines (int row, int col, Serializable data) { while (m_printRows.getRowCount() <= row) m_printRows.addRow(null); m_printRows.setRowIndex(row); List