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