Package org.pentaho.reporting.engine.classic.core.layout

Source Code of org.pentaho.reporting.engine.classic.core.layout.FlowRenderer

/*
* 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;

import org.pentaho.reporting.engine.classic.core.ReportDefinition;
import org.pentaho.reporting.engine.classic.core.layout.model.LogicalPageBox;
import org.pentaho.reporting.engine.classic.core.layout.model.PageBreakPositionList;
import org.pentaho.reporting.engine.classic.core.layout.output.ContentProcessingException;
import org.pentaho.reporting.engine.classic.core.layout.output.IterativeOutputProcessor;
import org.pentaho.reporting.engine.classic.core.layout.output.LayoutPagebreakHandler;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessor;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessorFeature;
import org.pentaho.reporting.engine.classic.core.layout.process.ApplyAutoCommitPageHeaderStep;
import org.pentaho.reporting.engine.classic.core.layout.process.ApplyPageShiftValuesStep;
import org.pentaho.reporting.engine.classic.core.layout.process.CleanFlowBoxesStep;
import org.pentaho.reporting.engine.classic.core.layout.process.CleanPaginatedBoxesStep;
import org.pentaho.reporting.engine.classic.core.layout.process.FillFlowPagesStep;
import org.pentaho.reporting.engine.classic.core.layout.process.FlowPaginationStep;
import org.pentaho.reporting.engine.classic.core.layout.process.PaginationResult;
import org.pentaho.reporting.engine.classic.core.util.InstanceID;

/**
* A flow renderer is a light-weight paginating renderer. It does not care about the page-size but searches for manual
* breaks. Once a manual break is encountered, the flow shifts and creates a page-event. (This is the behavior of the
* old table-exporters.)
* <p/>
* This implementation is a mix of a paginated and streaming renderer.
*
* @author Thomas Morgner
*/
public class FlowRenderer extends AbstractRenderer
{
  private FlowPaginationStep paginationStep;
  private FillFlowPagesStep fillPhysicalPagesStep;
  private CleanPaginatedBoxesStep cleanPaginatedBoxesStep;
  private CleanFlowBoxesStep cleanFlowBoxesStep;
  private ApplyPageShiftValuesStep applyPageShiftValuesStep;
  private ApplyAutoCommitPageHeaderStep applyAutoCommitPageHeaderStep;
  private int flowCount;
  private long lastPageAge;
  private boolean pageStartPending;

  public FlowRenderer(final OutputProcessor outputProcessor)
  {
    super(outputProcessor);
    this.paginationStep = new FlowPaginationStep();
    this.fillPhysicalPagesStep = new FillFlowPagesStep();
    this.cleanPaginatedBoxesStep = new CleanPaginatedBoxesStep();
    this.cleanFlowBoxesStep = new CleanFlowBoxesStep();
    this.applyPageShiftValuesStep = new ApplyPageShiftValuesStep();
    this.applyAutoCommitPageHeaderStep = new ApplyAutoCommitPageHeaderStep();
  }

  public void startReport(final ReportDefinition report)
  {
    super.startReport(report);
    lastPageAge = System.currentTimeMillis();
  }

  protected boolean isPageFinished()
  {
    final LogicalPageBox pageBox = getPageBox();
//    final long sizeBeforePagination = pageBox.getHeight();
    //final LogicalPageBox clone = (LogicalPageBox) pageBox.deriveForAdvance(true);
    final PaginationResult pageBreak = paginationStep.performPagebreak(pageBox);
    if (pageBreak.isOverflow() || pageBox.isOpen() == false)
    {
      setLastStateKey(pageBreak.getLastVisibleState());
      return true;
    }
    return false;
  }

  protected void debugPrint(final LogicalPageBox pageBox)
  {
//    ModelPrinter.print(pageBox);
  }


  public void processIncrementalUpdate(final boolean performOutput) throws ContentProcessingException
  {
    if (isDirty() == false)
    {
//      Log.debug ("Not dirty, no update needed.");
      return;
    }
    clearDirty();

    final OutputProcessor outputProcessor = getOutputProcessor();
    if (outputProcessor instanceof IterativeOutputProcessor == false ||
        outputProcessor.getMetaData().isFeatureSupported(OutputProcessorFeature.ITERATIVE_RENDERING) == false)
    {
//      Log.debug ("No incremental system.");
      return;
    }


    final LogicalPageBox pageBox = getPageBox();
    pageBox.setPageEnd(pageBox.getHeight());
//    Log.debug ("Computing Incremental update: " + pageBox.getPageOffset() + " " + pageBox.getPageEnd());
    // shiftBox(pageBox, true);

    if (pageBox.isOpen())
    {
      final IterativeOutputProcessor io = (IterativeOutputProcessor) outputProcessor;
      if (applyAutoCommitPageHeaderStep.compute(pageBox))
      {
        io.processIterativeContent(pageBox, performOutput);
        cleanFlowBoxesStep.compute(pageBox);
      }
    }
  }

  protected boolean performPagination(final LayoutPagebreakHandler layoutPagebreakHandler,
                                      final boolean performOutput)
      throws ContentProcessingException
  {
    final OutputProcessor outputProcessor = getOutputProcessor();
    // next: perform pagination.
    final LogicalPageBox pageBox = getPageBox();
//    final long sizeBeforePagination = pageBox.getHeight();
    //final LogicalPageBox clone = (LogicalPageBox) pageBox.deriveForAdvance(true);
    final PaginationResult pageBreak = paginationStep.performPagebreak(pageBox);
    if (pageBreak.isOverflow() || pageBox.isOpen() == false)
    {
      setLastStateKey(pageBreak.getLastVisibleState());
//      final long sizeAfterPagination = pageBox.getHeight();
      setPagebreaks(getPagebreaks() + 1);
      pageBox.setAllVerticalBreaks(pageBreak.getAllBreaks());

      flowCount += 1;
      debugPrint(pageBox);

      // A new page has been started. Recover the page-grid, then restart
      // everything from scratch. (We have to recompute, as the pages may
      // be different now, due to changed margins or page definitions)
      final long nextOffset = pageBox.computePageEnd();
      pageBox.setPageEnd(nextOffset);
      final long pageOffset = pageBox.getPageOffset();

      if (performOutput)
      {
        if (outputProcessor.isNeedAlignedPage())
        {
          final LogicalPageBox box = fillPhysicalPagesStep.compute(pageBox, pageOffset, nextOffset);
//          DebugLog.log("Processing contents for Page " + flowCount + " Page-Offset: " + pageOffset + " -> " + nextOffset);

          outputProcessor.processContent(box);
        }
        else
        {
//          DebugLog.log("Processing fast contents for Page " + flowCount + " Page-Offset: " + pageOffset + " -> " + nextOffset);
          outputProcessor.processContent(pageBox);
        }
      }
      else
      {
//        DebugLog.log("Recomputing contents for Page " + flowCount + " Page-Offset: " + pageOffset + " -> " + nextOffset);
        outputProcessor.processRecomputedContent(pageBox);
      }

      // Now fire the pagebreak. This goes through all layers and informs all
      // components, that a pagebreak has been encountered and possibly a
      // new page has been set. It does not save the state or perform other
      // expensive operations. However, it updates the 'isPagebreakEncountered'
      // flag, which will be active until the input-feed received a new event.
      //      Log.debug("PageTime " + (currentPageAge - lastPageAge));
      lastPageAge = System.currentTimeMillis();

      final boolean repeat = pageBox.isOpen() || pageBreak.isOverflow();
      if (repeat)
      {
        // pageBox.setAllVerticalBreaks(pageBreak.getAllBreaks());
        // First clean all boxes that have been marked as finished. This reduces the overall complexity of the
        // pagebox and improves performance on huge reports.
        cleanFlowBoxesStep.compute(pageBox);

        final long l = cleanPaginatedBoxesStep.compute(pageBox);
        if (l > 0)
        {
//          Log.debug ("Apply shift afterwards " + l);
          final InstanceID shiftNode = cleanPaginatedBoxesStep.getShiftNode();
          applyPageShiftValuesStep.compute(pageBox, l, shiftNode);
          debugPrint(pageBox);
        }

        pageBox.setPageOffset(nextOffset);
        if (pageBreak.isNextPageContainsContent())
        {
          if (layoutPagebreakHandler != null)
          {
            layoutPagebreakHandler.pageStarted();
          }
          return true;
        }
        // No need to try again, we know that the result will not change, as the next page is
        // empty. (We already tested it.)
        pageStartPending = true;
        return false;
      }
      else
      {
        outputProcessor.processingFinished();
        pageBox.setPageOffset(nextOffset);
        return false;
      }
    }
    else if (outputProcessor instanceof IterativeOutputProcessor &&
        outputProcessor.getMetaData().isFeatureSupported(OutputProcessorFeature.ITERATIVE_RENDERING))
    {
      processIncrementalUpdate(performOutput);
//      final IterativeOutputProcessor io = (IterativeOutputProcessor) outputProcessor;
//      io.processIterativeContent(pageBox, performOutput);
//      cleanFlowBoxesStep.compute(pageBox);
    }
    return false;
  }

  public int getFlowCount()
  {
    return flowCount;
  }

  public boolean isCurrentPageEmpty()
  {
    // todo: Invent a test that checks whether the page is currently empty.
    final LogicalPageBox logicalPageBox = getPageBox();
    final PageBreakPositionList breakPositionList = logicalPageBox.getAllVerticalBreaks();
    final long masterBreak = breakPositionList.getLastMasterBreak();
    final boolean nextPageContainsContent = (logicalPageBox.getHeight() > masterBreak);
    return nextPageContainsContent == false;
  }

  public boolean clearPendingPageStart(final LayoutPagebreakHandler layoutPagebreakHandler)
  {
    if (pageStartPending == false)
    {
      return false;
    }

    if (layoutPagebreakHandler != null)
    {
      layoutPagebreakHandler.pageStarted();
    }
    pageStartPending = false;
    return true;
  }

  public boolean isPageStartPending()
  {
    return pageStartPending;
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.layout.FlowRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.