/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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 Lesser General Public License for more details. * * Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.reporting.engine.classic.core.layout.process; import org.pentaho.reporting.engine.classic.core.layout.model.table.TableCellRenderBox; import org.pentaho.reporting.engine.classic.core.layout.model.table.TableRenderBox; import org.pentaho.reporting.engine.classic.core.layout.model.table.TableRowRenderBox; import org.pentaho.reporting.engine.classic.core.layout.model.table.TableSectionRenderBox; import org.pentaho.reporting.engine.classic.core.layout.model.table.columns.TableColumnModel; import org.pentaho.reporting.engine.classic.core.layout.model.table.rows.TableRowModel; /** * Updates the row heights in the model for a table. This is slightly more complex than the row-layout system, as * row-spans distribute extra heights to all cells involved. * * @author Thomas Morgner */ public class TableRowHeightCalculation { private static class TableInfoStructure { private TableRenderBox table; private TableInfoStructure parent; private TableColumnModel columnModel; private TableRowModel rowModel; private int rowNumber; private long filledHeight; public TableInfoStructure( final TableRenderBox table, final TableInfoStructure parent ) { this.table = table; this.parent = parent; this.columnModel = table.getColumnModel(); } public TableInfoStructure pop() { return parent; } public long getFilledHeight() { return filledHeight; } public void setFilledHeight( final long filledHeight ) { if ( filledHeight < 0 ) { throw new IllegalStateException( "Filled height is negative: " + filledHeight ); } this.filledHeight = filledHeight; } public TableRenderBox getTable() { return table; } public TableColumnModel getColumnModel() { return columnModel; } public void setRowModel( final TableRowModel rowModel ) { this.rowModel = rowModel; } public void setRowNumber( final int rowNumber ) { this.rowNumber = rowNumber; } public long getPreferredRowSize( final int offset ) { return rowModel.getPreferredRowSize( this.rowNumber + offset ); } public long getValidatedRowSize( final int offset ) { return rowModel.getValidatedRowSize( this.rowNumber + offset ); } public void updateValidatedSize( final int rowSpan, final int leading, final long cachedHeight ) { rowModel.updateValidatedSize( this.rowNumber, rowSpan, leading, cachedHeight ); } } private TableInfoStructure currentTable; private boolean secondPass; private TableRowHeightApplyStep applyStep; public TableRowHeightCalculation( final boolean secondPass ) { this.applyStep = new TableRowHeightApplyStep(); this.secondPass = secondPass; } public void reset() { currentTable = null; } public void startTableBox( final TableRenderBox box ) { currentTable = new TableInfoStructure( box, currentTable ); } public void finishTable( final TableRenderBox box ) { final long newHeight = currentTable.getFilledHeight(); box.setCachedHeight( newHeight ); currentTable = currentTable.pop(); } public void startTableSection( final TableSectionRenderBox sectionBox ) { currentTable.setRowModel( sectionBox.getRowModel() ); } public void startTableCell( final TableCellRenderBox box ) { if ( secondPass == false ) { long size = 0; for ( int i = 0; i < box.getRowSpan(); i += 1 ) { size += currentTable.getPreferredRowSize( i ); } box.setCachedHeight( size ); } else { long size = 0; for ( int i = 0; i < box.getRowSpan(); i += 1 ) { size += currentTable.getValidatedRowSize( i ); } box.setCachedHeight( size ); } } public void finishTableCell( final TableCellRenderBox cellBox, final long cachedHeight ) { if ( secondPass == false ) { final int rowSpan = cellBox.getRowSpan(); currentTable.updateValidatedSize( rowSpan, 0, cachedHeight ); } else { long size = 0; for ( int i = 0; i < cellBox.getRowSpan(); i += 1 ) { size += currentTable.getValidatedRowSize( i ); } cellBox.setCachedHeight( size ); } } public void startTableRow( final TableRowRenderBox box ) { currentTable.setRowNumber( box.getRowIndex() ); } public void finishTableSection( final TableSectionRenderBox section ) { final TableRowModel rowModel = section.getRowModel(); if ( section.getRowModelAge() != section.getChangeTracker() ) { rowModel.validateActualSizes(); section.setRowModelAge( section.getChangeTracker() ); } final long usedTableBodyHeight = applyStep.start( section ); currentTable.setFilledHeight( usedTableBodyHeight + currentTable.getFilledHeight() ); currentTable.setRowModel( null ); } }