/*
* 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;
import java.awt.Insets;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import org.pentaho.reporting.engine.classic.core.util.PageFormatFactory;
import org.pentaho.reporting.engine.classic.core.util.PageSize;
import org.pentaho.reporting.libraries.serializer.SerializerHelper;
/**
* A simple page definition defines a logical page, for which all physical pages have the same size.
* <p/>
* The page area is a rectangle.
*
* @author Thomas Morgner
*/
public class SimplePageDefinition implements PageDefinition {
/**
* The page format.
*/
private transient PageFormat format;
/**
* The page positions of the physical pages.
*/
private transient Rectangle2D[] pagePositions;
/**
* The number of columns in the page grid.
*/
private int pageCountHorizontal;
/**
* The number of rows in the page grid.
*/
private int pageCountVertical;
/**
* Creates a new SimplePageDefinition object.
*
* @param format
* the pageformat used as base.
* @param x
* the number of physical pages in a row.
* @param y
* the number of physical pages in a column.
*/
public SimplePageDefinition( final PageFormat format, final int x, final int y ) {
if ( format == null ) {
throw new NullPointerException( "Format must not be null" );
}
if ( x < 1 ) {
throw new IllegalArgumentException( "PageCount must be greater or equal to 1" );
}
if ( y < 1 ) {
throw new IllegalArgumentException( "PageCount must be greater or equal to 1" );
}
this.format = (PageFormat) format.clone();
this.pageCountHorizontal = x;
this.pageCountVertical = y;
this.pagePositions = new Rectangle2D[pageCountHorizontal * pageCountVertical];
final float width = (float) format.getImageableWidth();
final float height = (float) format.getImageableHeight();
float pageStartY = 0;
for ( int vert = 0; vert < pageCountVertical; vert++ ) {
float pageStartX = 0;
for ( int hor = 0; hor < pageCountHorizontal; hor++ ) {
final Rectangle2D rect = new Rectangle2D.Float( pageStartX, pageStartY, width, height );
pagePositions[vert * pageCountHorizontal + hor] = rect;
pageStartX += width;
}
pageStartY += height;
}
}
/**
* Creates a 1x1 page defintion. The physical page size is equal to the logical page size.
*
* @param format
* the pageformat.
*/
public SimplePageDefinition( final PageFormat format ) {
this( format, 1, 1 );
}
/**
* Creates a 1x1 page defintion. The physical page size is equal to the logical page size.
*/
public SimplePageDefinition( final PageSize papersize, final int orientation, final Insets margins ) {
this( PageFormatFactory.create( papersize, orientation, margins ), 1, 1 );
}
/**
* Creates a 1x1 page defintion. The physical page size is equal to the logical page size.
*/
public SimplePageDefinition( final PageSize papersize ) {
this( PageFormatFactory.create( papersize, PageFormat.PORTRAIT, new Insets( 0, 0, 0, 0 ) ), 1, 1 );
}
/**
* Returns the number of physical pages in this page definition.
*
* @return the number of pages.
*/
public int getPageCount() {
return pageCountHorizontal * pageCountVertical;
}
/**
* Returns the physical page format for the given position.
*
* @param pos
* the position in the page grid.
* @return a clone of the pageformat at the specified positon.
*/
public PageFormat getPageFormat( final int pos ) {
if ( pos < 0 || pos > getPageCount() ) {
throw new IndexOutOfBoundsException( "Index is invalid" );
}
return (PageFormat) format.clone();
}
/**
* Returns the printable area within the logical page area covered by the physical page at the given position.
*
* @param index
* the positon.
* @return the printable area for the page.
*/
public Rectangle2D getPagePosition( final int index ) {
if ( index < 0 || index > getPageCount() ) {
throw new IndexOutOfBoundsException( "Index is invalid" );
}
return pagePositions[index].getBounds2D();
}
/**
* Returns all page position known to this page definition.
*
* @return the page positions.
*/
public Rectangle2D[] getPagePositions() {
final int length = pagePositions.length;
final Rectangle2D[] rects = new Rectangle2D[length];
for ( int i = 0; i < length; i++ ) {
rects[i] = pagePositions[i].getBounds2D();
}
return rects;
}
/**
* Returns the total height of the logical page.
*
* @return the height of the page.
*/
public float getHeight() {
return (float) ( format.getImageableHeight() * pageCountVertical );
}
/**
* Returns the total width of the logical page.
*
* @return the width of the page.
*/
public float getWidth() {
return (float) ( format.getImageableWidth() * pageCountHorizontal );
}
/**
* Deserizalize the report and restore the pageformat.
*
* @param out
* the objectoutput stream
* @throws java.io.IOException
* if errors occur
*/
private void writeObject( final ObjectOutputStream out ) throws IOException {
out.defaultWriteObject();
final SerializerHelper instance = SerializerHelper.getInstance();
instance.writeObject( format, out );
final int length = pagePositions.length;
out.writeInt( length );
for ( int i = 0; i < length; i++ ) {
instance.writeObject( pagePositions[i], out );
}
}
/**
* Resolve the pageformat, as PageFormat is not serializable.
*
* @param in
* the input stream.
* @throws java.io.IOException
* if there is an IO problem.
* @throws ClassNotFoundException
* if there is a class problem.
*/
private void readObject( final ObjectInputStream in ) throws IOException, ClassNotFoundException {
in.defaultReadObject();
final SerializerHelper instance = SerializerHelper.getInstance();
format = (PageFormat) instance.readObject( in );
final int length = in.readInt();
pagePositions = new Rectangle2D[length];
for ( int i = 0; i < length; i++ ) {
pagePositions[i] = (Rectangle2D) instance.readObject( in );
}
}
/**
* Creates a copy of this page definition.
*
* @return a clone of this page definition object.
* @throws CloneNotSupportedException
*/
public Object clone() throws CloneNotSupportedException {
final SimplePageDefinition pdef = (SimplePageDefinition) super.clone();
pdef.format = (PageFormat) format.clone();
return pdef;
}
/**
* Checks whether this page definition object is equal to the given object.
*
* @param obj
* the other object.
* @return true, if that object is the same as this object, false otherwise.
*/
public boolean equals( final Object obj ) {
if ( this == obj ) {
return true;
}
if ( !( obj instanceof SimplePageDefinition ) ) {
return false;
}
final SimplePageDefinition simplePageDefinition = (SimplePageDefinition) obj;
if ( pageCountHorizontal != simplePageDefinition.pageCountHorizontal ) {
return false;
}
if ( pageCountVertical != simplePageDefinition.pageCountVertical ) {
return false;
}
if ( !PageFormatFactory.isEqual( format, simplePageDefinition.format ) ) {
return false;
}
if ( !Arrays.equals( pagePositions, simplePageDefinition.pagePositions ) ) {
return false;
}
return true;
}
/**
* Returns the number of horizontal pages in this page definition. That number is always greater than zero.
*
* @return the horizontal page count.
*/
public int getPageCountHorizontal() {
return pageCountHorizontal;
}
/**
* Returns the number of vertical pages in this page definition. That number is always greater than zero.
*
* @return the vertical page count.
*/
public int getPageCountVertical() {
return pageCountVertical;
}
/**
* Computes a hashcode for this page definition.
*
* @return the hashcode.
*/
public int hashCode() {
int result = format.hashCode();
result = 29 * result + pageCountHorizontal;
result = 29 * result + pageCountVertical;
return result;
}
public PageFormat getPageFormat() {
return format;
}
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "SimplePageDefinition" );
sb.append( "{format=" ).append( PageFormatFactory.printPageFormat( format ) );
sb.append( ", pagePositions=" ).append( pagePositions == null ? "null" : Arrays.asList( pagePositions ).toString() );
sb.append( ", pageCountHorizontal=" ).append( pageCountHorizontal );
sb.append( ", pageCountVertical=" ).append( pageCountVertical );
sb.append( '}' );
return sb.toString();
}
}