package net.sf.openrocket.gui.print.visitor;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Set;
import net.sf.openrocket.gui.print.AbstractPrintable;
import net.sf.openrocket.gui.print.ITextHelper;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
/**
* Common logic for printing strategies.
*/
public abstract class AbstractPrintStrategy<V> {
/**
* The logger.
*/
protected static final Logger log = LoggerFactory.getLogger(AbstractPrintStrategy.class);
/**
* The iText document.
*/
protected Document document;
/**
* The direct iText writer.
*/
protected PdfWriter writer;
/**
* The stages selected.
*/
protected Set<Integer> stages;
/**
* Strategy for fitting multiple components onto a page.
*/
protected PageFitPrintStrategy pageFitPrint;
/**
* Constructor.
*
* @param doc the document
* @param pageFit the page fitting strategy
* @param theWriter the pdf writer
* @param theStages the set of stages in the rocket
*/
public AbstractPrintStrategy(Document doc, PageFitPrintStrategy pageFit, PdfWriter theWriter,
Set<Integer> theStages) {
document = doc;
pageFitPrint = pageFit;
writer = theWriter;
stages = theStages;
}
/**
* Recurse through the given rocket component.
*
* @param root the root component; all children will be printed recursively
*/
public V writeToDocument(final RocketComponent root) {
return goDeep(root.getChildren());
}
/**
* Recurse through the given rocket component.
*
* @param theRc an array of rocket components; all children will be printed recursively
*/
protected abstract V goDeep(List<RocketComponent> theRc);
/**
* Determine if the image will fit on the given page.
*
* @param pageSize the page size
* @param wImage the width of the thing to be printed
* @param hImage the height of the thing to be printed
*
* @return true if the thing to be printed will fit on a single page
*/
protected boolean fitsOnOnePage(Dimension pageSize, double wImage, double hImage) {
double wPage = pageSize.getWidth() - PageFitPrintStrategy.MARGIN * 2;
double hPage = pageSize.getHeight() - PageFitPrintStrategy.MARGIN * 2;
int wRatio = (int) Math.ceil(wImage / wPage);
int hRatio = (int) Math.ceil(hImage / hPage);
return wRatio <= 1.0d && hRatio <= 1.0d;
}
/**
* Get the dimensions of the paper page.
*
* @return an internal Dimension
*/
protected Dimension getPageSize() {
return new Dimension(document.getPageSize().getWidth(),
document.getPageSize().getHeight());
}
/**
* Determine if the strategy's set of stage numbers (to print) contains the specified stage.
*
* @param stageNumber a stage number
*
* @return true if the strategy contains the stage number provided
*/
public boolean shouldPrintStage(int stageNumber) {
if (stages == null || stages.isEmpty()) {
return false;
}
for (final Integer stage : stages) {
if (stage == stageNumber) {
return true;
}
}
return false;
}
void render(final AbstractPrintable thePrintable) throws DocumentException {
java.awt.Dimension size = thePrintable.getSize();
final Dimension pageSize = getPageSize();
if (fitsOnOnePage(pageSize, size.getWidth(), size.getHeight())) {
pageFitPrint.addComponent(thePrintable);
}
else {
BufferedImage image = (BufferedImage) thePrintable.createImage();
ITextHelper.renderImageAcrossPages(new Rectangle(pageSize.getWidth(), pageSize.getHeight()),
document, writer, image);
document.newPage();
}
}
}