/*
* 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 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.core.layout.process.linebreak;
import java.util.Stack;
import org.pentaho.reporting.engine.classic.core.layout.model.InlineRenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.LayoutNodeTypes;
import org.pentaho.reporting.engine.classic.core.layout.model.ParagraphRenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderNode;
/**
* Creation-Date: 25.04.2007, 13:44:48
*
* @author Thomas Morgner
*/
public final class FullLinebreaker implements ParagraphLinebreaker
{
private RenderBox insertationPoint;
private ParagraphRenderBox paragraphRenderBox;
private Object suspendItem;
private boolean breakRequested;
public FullLinebreaker(final ParagraphRenderBox paragraphRenderBox)
{
this.paragraphRenderBox = paragraphRenderBox;
final RenderBox pool = (RenderBox) paragraphRenderBox.getPool().deriveFrozen(false);
final RenderBox lineboxContainer = this.paragraphRenderBox.createLineboxContainer();
lineboxContainer.clear();
lineboxContainer.addGeneratedChild(pool);
this.paragraphRenderBox.setLineBoxAge(0);
this.insertationPoint = pool;
}
public boolean isWritable()
{
return true;
}
public void startBlockBox(final RenderBox child)
{
final RenderBox derived = (RenderBox) child.deriveFrozen(false);
insertationPoint.addGeneratedChild(derived);
insertationPoint = derived;
if (suspendItem != null)
{
suspendItem = derived.getInstanceId();
}
}
public void finishBlockBox(final RenderBox box)
{
insertationPoint = insertationPoint.getParent();
if (suspendItem == box.getInstanceId())
{
suspendItem = null;
}
}
public ParagraphLinebreaker startParagraphBox(final ParagraphRenderBox box)
{
startBlockBox(box);
return new FullLinebreaker((ParagraphRenderBox) insertationPoint);
}
public void finishParagraphBox(final ParagraphRenderBox box)
{
finishBlockBox(box);
}
public boolean isSuspended()
{
return suspendItem != null;
}
public FullLinebreaker startComplexLayout()
{
return this;
}
public void finish()
{
paragraphRenderBox.setLineBoxAge(paragraphRenderBox.getPool().getChangeTracker());
}
public void startInlineBox(final InlineRenderBox box)
{
final RenderBox child = (RenderBox) box.deriveFrozen(false);
insertationPoint.addGeneratedChild(child);
insertationPoint = child;
}
public void finishInlineBox(final InlineRenderBox box)
{
insertationPoint = insertationPoint.getParent();
}
public void addNode(final RenderNode node)
{
insertationPoint.addGeneratedChild(node.deriveFrozen(true));
}
public void performBreak()
{
// If we come that far, it means, we have a forced linebreak and we
// are a node in the middle of the tree ..
final Stack contexts = new Stack();
// perform a simple split
// as long as the splitted element is at the end of it's box, it is not
// needed to split the box at all. Just let it end naturally is enough for
// them to look good.
// As the real context (from the break-State) is currently being built,
// we have to use the original pool to query the 'is-end-of-line' flag.
RenderBox context = insertationPoint;
final RenderBox lines = paragraphRenderBox.getLineboxContainer();
while (context != lines)
{
// save the context ..
if (((context.getNodeType() & LayoutNodeTypes.MASK_BOX_INLINE) == LayoutNodeTypes.MASK_BOX_INLINE) == false)
{
throw new IllegalStateException("Confused: I expect InlineBoxes ..");
}
final InlineRenderBox inline = (InlineRenderBox) context;
contexts.push(inline.split(RenderNode.HORIZONTAL_AXIS));
context = context.getParent();
}
// reset to a known state and add all saved contexts ..
insertationPoint = lines;
while (contexts.isEmpty() == false)
{
final RenderBox box = (RenderBox) contexts.pop();
insertationPoint.addGeneratedChild(box);
insertationPoint = box;
}
breakRequested = false;
}
public boolean isBreakRequested()
{
return breakRequested;
}
public void setBreakRequested(final boolean breakRequested)
{
this.breakRequested = breakRequested;
}
}