1 package net.sf.openrocket.gui.print.visitor;
3 import com.itextpdf.text.Document;
4 import com.itextpdf.text.DocumentException;
5 import com.itextpdf.text.Rectangle;
6 import com.itextpdf.text.pdf.PdfWriter;
7 import net.sf.openrocket.gui.print.AbstractPrintable;
8 import net.sf.openrocket.gui.print.ITextHelper;
9 import net.sf.openrocket.gui.print.PrintUnit;
10 import net.sf.openrocket.gui.print.PrintableNoseCone;
11 import net.sf.openrocket.gui.print.PrintableTransition;
12 import net.sf.openrocket.logging.LogHelper;
13 import net.sf.openrocket.rocketcomponent.NoseCone;
14 import net.sf.openrocket.rocketcomponent.RocketComponent;
15 import net.sf.openrocket.rocketcomponent.Transition;
16 import net.sf.openrocket.startup.Application;
18 import java.awt.image.BufferedImage;
19 import java.util.List;
23 * A strategy for drawing transition/shroud/nose cone templates.
25 public class TransitionStrategy {
30 private static final LogHelper log = Application.getLogger();
35 protected Document document;
38 * The direct iText writer.
40 protected PdfWriter writer;
43 * The stages selected.
45 protected Set<Integer> stages;
48 * Strategy for fitting multiple components onto a page.
50 protected PageFitPrintStrategy pageFitPrint;
55 * @param doc The iText document
56 * @param theWriter The direct iText writer
57 * @param theStagesToVisit The stages to be visited by this strategy
59 public TransitionStrategy(Document doc, PdfWriter theWriter, Set<Integer> theStagesToVisit, PageFitPrintStrategy pageFit) {
62 stages = theStagesToVisit;
63 pageFitPrint = pageFit;
67 * Recurse through the given rocket component.
69 * @param root the root component; all children will be visited recursively
70 * @param noseCones nose cones are a special form of a transition; if true, then print nose cones
72 * @return true if a transition/nosecone was rendered
74 public boolean writeToDocument(final RocketComponent root, boolean noseCones) {
75 List<RocketComponent> rc = root.getChildren();
76 return goDeep(rc, noseCones);
81 * Recurse through the given rocket component.
83 * @param theRc an array of rocket components; all children will be visited recursively
84 * @param noseCones nose cones are a special form of a transition; if true, then print nose cones
86 * @return true if a transition/nosecone was rendered
88 protected boolean goDeep(final List<RocketComponent> theRc, boolean noseCones) {
89 for (RocketComponent rocketComponent : theRc) {
90 if (rocketComponent instanceof NoseCone) {
92 return render((Transition) rocketComponent);
95 else if (rocketComponent instanceof Transition && !noseCones) {
96 return render((Transition) rocketComponent);
98 else if (rocketComponent.getChildCount() > 0) {
99 return goDeep(rocketComponent.getChildren(), noseCones);
106 * The core behavior of this visitor.
108 * @param component the object to extract info about; a graphical image of the transition shape is drawn to the
111 * @return true, always
113 private boolean render(final Transition component) {
115 AbstractPrintable pfs;
116 if (component instanceof NoseCone) {
117 pfs = new PrintableNoseCone((NoseCone) component);
120 pfs = new PrintableTransition(component);
123 java.awt.Dimension size = pfs.getSize();
124 final Dimension pageSize = getPageSize();
125 if (fitsOnOnePage(pageSize, size.getWidth(), size.getHeight())) {
126 pageFitPrint.addComponent(pfs);
129 int off = (int) (PrintUnit.POINTS_PER_INCH * 0.3f);
130 pfs.setPrintOffset(off, off);
131 BufferedImage image = (BufferedImage) pfs.createImage();
132 ITextHelper.renderImageAcrossPages(new Rectangle(pageSize.getWidth(), pageSize.getHeight()),
133 document, writer, image);
137 catch (DocumentException e) {
138 log.error("Could not render the transition.", e);
144 * Determine if the image will fit on the given page.
146 * @param pageSize the page size
147 * @param wImage the width of the thing to be printed
148 * @param hImage the height of the thing to be printed
150 * @return true if the thing to be printed will fit on a single page
152 private boolean fitsOnOnePage(Dimension pageSize, double wImage, double hImage) {
153 double wPage = pageSize.getWidth();
154 double hPage = pageSize.getHeight();
156 int wRatio = (int) Math.ceil(wImage / wPage);
157 int hRatio = (int) Math.ceil(hImage / hPage);
159 return wRatio <= 1.0d && hRatio <= 1.0d;
163 * Get the dimensions of the paper page.
165 * @return an internal Dimension
167 protected Dimension getPageSize() {
168 return new Dimension(document.getPageSize().getWidth(),
169 document.getPageSize().getHeight());
173 * Convenience class to model a dimension.
191 public Dimension(float w, float h) {
201 public float getWidth() {
210 public float getHeight() {