/*!
* 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 );
}
}