create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / gui / print / visitor / PageFitPrintStrategy.java
1 /*
2  * PageFitPrintStrategy.java
3  */
4 package net.sf.openrocket.gui.print.visitor;
5
6 import com.itextpdf.text.Document;
7 import com.itextpdf.text.pdf.PdfContentByte;
8 import com.itextpdf.text.pdf.PdfWriter;
9 import net.sf.openrocket.gui.print.PrintUnit;
10 import net.sf.openrocket.gui.print.PrintableComponent;
11 import net.sf.openrocket.logging.LogHelper;
12 import net.sf.openrocket.rocketcomponent.RocketComponent;
13 import net.sf.openrocket.startup.Application;
14
15 import java.awt.Graphics2D;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.ListIterator;
19 import java.util.Set;
20
21 /**
22  * A strategy for drawing multiple rocket components onto as few pages as possible.
23  *
24  * @author Jason Blood <dyster2000@gmail.com>
25  */
26 public class PageFitPrintStrategy {
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         protected ArrayList<PrintableComponent> componentToPrint;
49
50     /**
51      * Constructor.
52      *
53      * @param doc              The iText document
54      * @param theWriter        The direct iText writer
55      */
56     public PageFitPrintStrategy(Document doc, PdfWriter theWriter) {
57         document = doc;
58         writer = theWriter;
59         componentToPrint = new ArrayList<PrintableComponent>();
60     }
61
62     /**
63      * Add a component we want to print.
64      *
65      * @param component The component to add for printing
66      */
67     public void addComponent(PrintableComponent component) {
68                 componentToPrint.add(component);
69     }
70
71     /**
72      * Recurse through the given rocket component.
73      *
74      * @param root the root component; all children will be printed recursively
75      */
76     public void writeToDocument (final RocketComponent root) {
77         fitPrintComponents();
78     }
79
80     /**
81      * Iterate through the components to print fitting them onto pages as best possible.
82      */
83     private void fitPrintComponents() {
84         final Dimension pageSize = getPageSize();
85         double wPage = pageSize.getWidth();
86         double hPage = pageSize.getHeight();
87         int marginX = (int)(PrintUnit.POINTS_PER_INCH * 0.3f);
88         int marginY = (int)(PrintUnit.POINTS_PER_INCH * 0.3f);
89         PdfContentByte cb = writer.getDirectContent();
90
91         Collections.sort(componentToPrint);
92
93         while (componentToPrint.size() > 0) {
94                 int pageY = marginY;
95                 Boolean anyAddedToRow;
96
97             Graphics2D g2 = cb.createGraphics(pageSize.width, pageSize.height);
98
99                 do {
100                         // Fill the row
101                         int rowX = marginX;
102                         int rowY = pageY;
103                         ListIterator<PrintableComponent> entry = componentToPrint.listIterator();
104                         anyAddedToRow = false;
105
106                         while (entry.hasNext()) {
107                                 PrintableComponent component = entry.next();
108                                 java.awt.Dimension dim = component.getSize();
109                                 if ((rowX + dim.width + marginX < wPage) && (rowY + dim.height + marginY < hPage)) {
110                                         component.setPrintOffset(rowX, rowY);
111                                         rowX += dim.width + marginX;
112                                         if (rowY + dim.height + marginY > pageY) {
113                                                 pageY = rowY + dim.height + marginY;
114                         }
115                                         entry.remove();
116                                         component.print(g2);
117                                         anyAddedToRow = true;
118                                 }
119                         }
120                 pageY += marginY;
121                 } while (anyAddedToRow);
122
123                 g2.dispose();
124                 document.newPage();
125         }
126     }
127
128     /**
129      * Get the dimensions of the paper page.
130      *
131      * @return an internal Dimension
132      */
133     protected Dimension getPageSize () {
134         return new Dimension(document.getPageSize().getWidth(),
135                              document.getPageSize().getHeight());
136     }
137
138     /**
139      * Convenience class to model a dimension.
140      */
141     class Dimension {
142         /** Width, in points. */
143         public float width;
144         /** Height, in points. */
145         public float height;
146
147         /**
148          * Constructor.
149          * @param w width
150          * @param h height
151          */
152         public Dimension (float w, float h) {
153             width = w;
154             height = h;
155         }
156
157         /**
158          * Get the width.
159          *
160          * @return  the width
161          */
162         public float getWidth () {
163             return width;
164         }
165
166         /**
167          * Get the height.
168          *
169          * @return the height
170          */
171         public float getHeight () {
172             return height;
173         }
174     }
175 }