bd45045587e9780361591ad8dc2d8ccd425b3343
[debian/openrocket] / core / src / net / sf / openrocket / gui / print / visitor / TransitionStrategy.java
1 package net.sf.openrocket.gui.print.visitor;
2
3 import com.itextpdf.text.Document;
4 import com.itextpdf.text.DocumentException;
5 import com.itextpdf.text.Rectangle;
6 import com.itextpdf.text.pdf.PdfContentByte;
7 import com.itextpdf.text.pdf.PdfWriter;
8 import net.sf.openrocket.gui.print.AbstractPrintableTransition;
9 import net.sf.openrocket.gui.print.ITextHelper;
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;
17
18 import java.awt.*;
19 import java.awt.image.BufferedImage;
20 import java.util.List;
21 import java.util.Set;
22
23 /**
24  * A strategy for drawing transition/shroud/nose cone templates.
25  */
26 public class TransitionStrategy {
27
28     /**
29      * The logger.
30      */
31     private static final LogHelper log = Application.getLogger();
32
33     /**
34      * The iText document.
35      */
36     protected Document document;
37
38     /**
39      * The direct iText writer.
40      */
41     protected PdfWriter writer;
42
43     /**
44      * The stages selected.
45      */
46     protected Set<Integer> stages;
47
48     /**
49      * Strategy for fitting multiple components onto a page.
50      */
51         protected PageFitPrintStrategy pageFitPrint;
52
53     /**
54      * Constructor.
55      *
56      * @param doc              The iText document
57      * @param theWriter        The direct iText writer
58      * @param theStagesToVisit The stages to be visited by this strategy
59      */
60     public TransitionStrategy(Document doc, PdfWriter theWriter, Set<Integer> theStagesToVisit, PageFitPrintStrategy pageFit) {
61         document = doc;
62         writer = theWriter;
63         stages = theStagesToVisit;
64         pageFitPrint = pageFit;
65     }
66
67     /**
68      * Recurse through the given rocket component.
69      *
70      * @param root      the root component; all children will be visited recursively
71      * @param noseCones nose cones are a special form of a transition; if true, then print nose cones
72      */
73     public void writeToDocument(final RocketComponent root, boolean noseCones) {
74         List<RocketComponent> rc = root.getChildren();
75         goDeep(rc, noseCones);
76     }
77
78
79     /**
80      * Recurse through the given rocket component.
81      *
82      * @param theRc     an array of rocket components; all children will be visited recursively
83      * @param noseCones nose cones are a special form of a transition; if true, then print nose cones
84      */
85     protected void goDeep(final List<RocketComponent> theRc, boolean noseCones) {
86         for (RocketComponent rocketComponent : theRc) {
87             if (rocketComponent instanceof NoseCone) {
88                 if (noseCones) {
89                     render((Transition) rocketComponent);
90                 }
91             } else if (rocketComponent instanceof Transition && !noseCones) {
92                 render((Transition) rocketComponent);
93             } else if (rocketComponent.getChildCount() > 0) {
94                 goDeep(rocketComponent.getChildren(), noseCones);
95             }
96         }
97     }
98
99     /**
100      * The core behavior of this visitor.
101      *
102      * @param component the object to extract info about; a graphical image of the transition shape is drawn to the document
103      */
104     private void render(final Transition component) {
105         try {
106             AbstractPrintableTransition pfs;
107             if (component instanceof NoseCone) {
108                 pfs = new PrintableNoseCone(component);
109             } else {
110                 pfs = new PrintableTransition(component);
111             }
112
113             java.awt.Dimension size = pfs.getSize();
114             final Dimension pageSize = getPageSize();
115             if (fitsOnOnePage(pageSize, size.getWidth(), size.getHeight())) {
116                                 pageFitPrint.addComponent(pfs);
117                 //printOnOnePage(pfs);
118             } else {
119                 BufferedImage image = (BufferedImage) pfs.createImage();
120                 ITextHelper.renderImageAcrossPages(new Rectangle(pageSize.getWidth(), pageSize.getHeight()),
121                         document, writer, image);
122             }
123         } catch (DocumentException e) {
124             log.error("Could not render the transition.", e);
125         }
126     }
127
128     /**
129      * Determine if the image will fit on the given page.
130      *
131      * @param pageSize the page size
132      * @param wImage   the width of the thing to be printed
133      * @param hImage   the height of the thing to be printed
134      * @return true if the thing to be printed will fit on a single page
135      */
136     private boolean fitsOnOnePage(Dimension pageSize, double wImage, double hImage) {
137         double wPage = pageSize.getWidth();
138         double hPage = pageSize.getHeight();
139
140         int wRatio = (int) Math.ceil(wImage / wPage);
141         int hRatio = (int) Math.ceil(hImage / hPage);
142
143         return wRatio <= 1.0d && hRatio <= 1.0d;
144     }
145
146     /**
147      * Print the transition.
148      *
149      * @param theTransition the printable transition
150      */
151     /*private void printOnOnePage(final AbstractPrintableTransition theTransition) {
152         Dimension d = getPageSize();
153         PdfContentByte cb = writer.getDirectContent();
154         Graphics2D g2 = cb.createGraphics(d.width, d.height);
155         theTransition.print(g2);
156         g2.dispose();
157         document.newPage();
158     }*/
159
160     /**
161      * Get the dimensions of the paper page.
162      *
163      * @return an internal Dimension
164      */
165     protected Dimension getPageSize() {
166         return new Dimension(document.getPageSize().getWidth(),
167                 document.getPageSize().getHeight());
168     }
169
170     /**
171      * Convenience class to model a dimension.
172      */
173     class Dimension {
174         /**
175          * Width, in points.
176          */
177         public float width;
178         /**
179          * Height, in points.
180          */
181         public float height;
182
183         /**
184          * Constructor.
185          *
186          * @param w width
187          * @param h height
188          */
189         public Dimension(float w, float h) {
190             width = w;
191             height = h;
192         }
193
194         /**
195          * Get the width.
196          *
197          * @return the width
198          */
199         public float getWidth() {
200             return width;
201         }
202
203         /**
204          * Get the height.
205          *
206          * @return the height
207          */
208         public float getHeight() {
209             return height;
210         }
211     }
212 }