/* * 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) 2001 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors.. All rights reserved. */ package org.pentaho.reporting.engine.classic.core.layout.model; import org.pentaho.reporting.engine.classic.core.ElementAlignment; import org.pentaho.reporting.engine.classic.core.ReportAttributeMap; import org.pentaho.reporting.engine.classic.core.filter.types.AutoLayoutBoxType; import org.pentaho.reporting.engine.classic.core.layout.model.context.BoxDefinition; import org.pentaho.reporting.engine.classic.core.layout.style.ParagraphPoolboxStyleSheet; import org.pentaho.reporting.engine.classic.core.metadata.ElementType; import org.pentaho.reporting.engine.classic.core.states.ReportStateKey; import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys; import org.pentaho.reporting.engine.classic.core.style.StyleSheet; import org.pentaho.reporting.engine.classic.core.style.TextStyleKeys; import org.pentaho.reporting.engine.classic.core.util.InstanceID; /** * Creation-Date: 03.04.2007, 13:38:00 * * @author Thomas Morgner */ public final class ParagraphRenderBox extends BlockRenderBox { private static class LineBoxRenderBox extends BlockRenderBox { protected LineBoxRenderBox( final StyleSheet styleSheet, final ReportStateKey stateKey ) { super( styleSheet, new InstanceID(), BoxDefinition.EMPTY, AutoLayoutBoxType.INSTANCE, ReportAttributeMap.EMPTY_MAP, stateKey ); } public boolean isAcceptInlineBoxes() { return true; } } private ParagraphPoolBox pool; private LineBoxRenderBox lineboxContainer; private ElementAlignment textAlignment; private ElementAlignment lastLineAlignment; private long lineBoxAge; private long minorLayoutAge; private long minorLayoutValidationX1; private long minorLayoutValidationX2; private int poolSize; private long textIndent; private long firstLineIndent; private long cachedMaxChildX2; public ParagraphRenderBox( final StyleSheet styleSheet, final InstanceID instanceID, final BoxDefinition boxDefinition, final ElementType elementType, final ReportAttributeMap attributeMap, final ReportStateKey stateKey ) { super( styleSheet, instanceID, boxDefinition, elementType, attributeMap, stateKey ); pool = new ParagraphPoolBox( new ParagraphPoolboxStyleSheet( styleSheet ), instanceID, stateKey ); pool.setParent( this ); // level 3 means: Add all lineboxes to the paragraph // This gets auto-generated .. this.textAlignment = (ElementAlignment) styleSheet.getStyleProperty( ElementStyleKeys.ALIGNMENT, ElementAlignment.LEFT ); this.lastLineAlignment = textAlignment; if ( this.textAlignment == ElementAlignment.JUSTIFY ) { this.lastLineAlignment = ElementAlignment.LEFT; } final double rawTextIndent = styleSheet.getDoubleStyleProperty( TextStyleKeys.TEXT_INDENT, 0 ); final double rawFirstLineIndent = styleSheet.getDoubleStyleProperty( TextStyleKeys.FIRST_LINE_INDENT, rawTextIndent ); this.textIndent = RenderLength.resolveLength( 0, Math.max( 0, rawTextIndent ) ); this.firstLineIndent = RenderLength.resolveLength( 0, Math.max( 0, rawFirstLineIndent ) ); } /** * Derive creates a disconnected node that shares all the properties of the original node. The derived node will no * longer have any parent, silbling, child or any other relationships with other nodes. * * @return */ public RenderNode derive( final boolean deepDerive ) { final ParagraphRenderBox box = (ParagraphRenderBox) super.derive( deepDerive ); box.pool = (ParagraphPoolBox) pool.derive( deepDerive ); box.pool.setParent( box ); if ( lineboxContainer != null ) { box.lineboxContainer = (LineBoxRenderBox) lineboxContainer.derive( deepDerive ); box.lineboxContainer.setParent( box ); } if ( !deepDerive ) { box.lineBoxAge = 0; } return box; } public final void addChild( final RenderNode child ) { pool.addChild( child ); } /** * Removes all children. */ public final void clear() { pool.clear(); if ( lineboxContainer != null ) { lineboxContainer.clear(); } super.clear(); lineBoxAge = 0; } public final void clearLayout() { super.clear(); minorLayoutAge = 0; } public boolean isAppendable() { return pool.isAppendable(); } public boolean isEmpty() { return pool.isEmpty(); } public boolean isDiscardable() { return pool.isDiscardable(); } public ElementAlignment getLastLineAlignment() { return lastLineAlignment; } public ElementAlignment getTextAlignment() { return textAlignment; } public RenderBox getLineboxContainer() { return lineboxContainer; } public boolean isComplexParagraph() { return lineboxContainer != null; } public RenderBox createLineboxContainer() { if ( lineboxContainer == null ) { this.lineboxContainer = new LineBoxRenderBox( pool.getStyleSheet(), getStateKey() ); this.lineboxContainer.setParent( this ); } return lineboxContainer; } public RenderBox getEffectiveLineboxContainer() { if ( lineboxContainer == null ) { return pool; } return lineboxContainer; } public ParagraphPoolBox getPool() { return pool; } public long getLineBoxAge() { return lineBoxAge; } public void setLineBoxAge( final long lineBoxAge ) { this.lineBoxAge = lineBoxAge; } public long getMinorLayoutAge() { return minorLayoutAge; } public void updateMinorLayoutAge() { this.minorLayoutAge = getEffectiveLineboxContainer().getChangeTracker(); this.minorLayoutValidationX1 = getContentAreaX1(); this.minorLayoutValidationX2 = getContentAreaX2(); } /** * The public-id for the paragraph is the pool-box. * * @return */ public InstanceID getInstanceId() { return pool.getInstanceId(); } public int getPoolSize() { return poolSize; } public void setPoolSize( final int poolSize ) { this.poolSize = poolSize; } public void close() { pool.close(); super.close(); } public int getNodeType() { return LayoutNodeTypes.TYPE_BOX_PARAGRAPH; } protected void increaseContentReferenceCount( final int count, final RenderNode source ) { if ( source != pool ) { return; } super.increaseContentReferenceCount( count, source ); } protected void increaseTableReferenceCount( final int count, final RenderNode source ) { if ( source != pool ) { return; } super.increaseTableReferenceCount( count, source ); } protected void decreaseContentReferenceCount( final int count, final RenderNode source ) { if ( source != pool ) { return; } super.decreaseContentReferenceCount( count, source ); } protected void decreaseTableReferenceCount( final int count, final RenderNode source ) { if ( source != pool ) { return; } super.decreaseTableReferenceCount( count, source ); } protected void increaseDescendantCount( final int count, final RenderNode source ) { if ( source != pool ) { return; } super.increaseDescendantCount( count, source ); } protected void decreaseDescendantCount( final int count, final RenderNode source ) { if ( source != pool ) { return; } super.decreaseDescendantCount( count, source ); } public long getTextIndent() { return textIndent; } public long getFirstLineIndent() { return firstLineIndent; } public boolean isAcceptInlineBoxes() { return true; } public boolean isLineBoxUnchanged() { final long lineBoxChangeTracker = getEffectiveLineboxContainer().getChangeTracker(); if ( lineBoxChangeTracker == getMinorLayoutAge() && minorLayoutValidationX1 == getContentAreaX1() && minorLayoutValidationX2 == getContentAreaX2() ) { // testing for both content-changes and positional changes due to subreports or other delayed content // inserting new data at an earlier point in the model. return true; } return false; } public long getCachedMaxChildX2() { return cachedMaxChildX2; } public void setCachedMaxChildX2( final long cachedMaxChildX2 ) { this.cachedMaxChildX2 = cachedMaxChildX2; } public void setCachedWidth( final long cachedWidth ) { super.setCachedWidth( cachedWidth ); } }