/*
* PageFitPrintStrategy.java
*/
package net.sf.openrocket.gui.print.visitor;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ListIterator;
import java.util.Set;
import net.sf.openrocket.gui.print.PrintUnit;
import net.sf.openrocket.gui.print.PrintableComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;
/**
* A strategy for drawing multiple rocket components onto as few pages as possible.
*
* @author Jason Blood <dyster2000@gmail.com>
*/
public class PageFitPrintStrategy {
/** The margin. */
public final static int MARGIN = (int)(PrintUnit.POINTS_PER_INCH * 0.3f);
/**
* The logger.
*/
private static final Logger log = LoggerFactory.getLogger(PageFitPrintStrategy.class);
/**
* The iText document.
*/
protected Document document;
/**
* The direct iText writer.
*/
protected PdfWriter writer;
/**
* The stages selected.
*/
protected Set<Integer> stages;
protected ArrayList<PrintableComponent> componentToPrint;
/**
* Constructor.
*
* @param doc The iText document
* @param theWriter The direct iText writer
*/
public PageFitPrintStrategy(Document doc, PdfWriter theWriter) {
document = doc;
writer = theWriter;
componentToPrint = new ArrayList<PrintableComponent>();
}
/**
* Add a component we want to print.
*
* @param component The component to add for printing
*/
public void addComponent(PrintableComponent component) {
componentToPrint.add(component);
}
/**
* Recurse through the given rocket component.
*/
public void writeToDocument () {
fitPrintComponents();
}
/**
* Iterate through the components to print fitting them onto pages as best possible.
*/
private void fitPrintComponents() {
final Dimension pageSize = getPageSize();
double wPage = pageSize.getWidth();
double hPage = pageSize.getHeight();
int marginX = MARGIN;
int marginY = MARGIN;
PdfContentByte cb = writer.getDirectContent();
Collections.sort(componentToPrint);
while (componentToPrint.size() > 0) {
int pageY = marginY;
Boolean anyAddedToRow;
Graphics2D g2 = createGraphics((float) wPage, (float) hPage, cb);
do {
// Fill the row
int rowX = marginX;
int rowY = pageY;
ListIterator<PrintableComponent> entry = componentToPrint.listIterator();
anyAddedToRow = false;
while (entry.hasNext()) {
PrintableComponent component = entry.next();
java.awt.Dimension dim = component.getSize();
if ((rowX + dim.width + marginX <= wPage) && (rowY + dim.height + marginY <= hPage)) {
component.setPrintOffset(rowX, rowY);
// Separate each component horizontally by a space equal to the margin
rowX += dim.width + marginX;
if (rowY + dim.height + marginY > pageY) {
pageY = rowY + dim.height + marginY;
}
entry.remove();
component.print(g2);
anyAddedToRow = true;
}
}
// Separate each component vertically by a space equal to the margin
pageY += marginY;
} while (anyAddedToRow);
g2.dispose();
document.newPage();
}
}
/**
* Create a graphics context.
*
* @param theWPage the width of the physical page
* @param theHPage the height of the physical
*
* @param theCb the pdf content byte instance
*
* @return a Graphics2D instance
*/
Graphics2D createGraphics(final float theWPage, final float theHPage, final PdfContentByte theCb) {
return theCb.createGraphics(theWPage, theHPage);
}
/**
* Get the dimensions of the paper page.
*
* @return an internal Dimension
*/
protected Dimension getPageSize () {
return new Dimension(document.getPageSize().getWidth(),
document.getPageSize().getHeight());
}
}