8cbfb6975259b4f7e30ad6fdf5e1edf2298ce340
[debian/openrocket] / src / net / sf / openrocket / gui / print / visitor / PartsDetailVisitorStrategy.java
1 /*
2  * PartsDetailVisitorStrategy.java
3  */
4 package net.sf.openrocket.gui.print.visitor;
5
6 import com.itextpdf.text.BadElementException;
7 import com.itextpdf.text.Chunk;
8 import com.itextpdf.text.Document;
9 import com.itextpdf.text.DocumentException;
10 import com.itextpdf.text.Element;
11 import com.itextpdf.text.Font;
12 import com.itextpdf.text.Image;
13 import com.itextpdf.text.Phrase;
14 import com.itextpdf.text.Rectangle;
15 import com.itextpdf.text.pdf.PdfPCell;
16 import com.itextpdf.text.pdf.PdfPTable;
17 import com.itextpdf.text.pdf.PdfWriter;
18 import net.sf.openrocket.gui.main.ComponentIcons;
19 import net.sf.openrocket.gui.print.ITextHelper;
20 import net.sf.openrocket.gui.print.PrintUtilities;
21 import net.sf.openrocket.gui.print.PrintableFinSet;
22 import net.sf.openrocket.material.Material;
23 import net.sf.openrocket.rocketcomponent.BodyComponent;
24 import net.sf.openrocket.rocketcomponent.BodyTube;
25 import net.sf.openrocket.rocketcomponent.Coaxial;
26 import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
27 import net.sf.openrocket.rocketcomponent.ExternalComponent;
28 import net.sf.openrocket.rocketcomponent.FinSet;
29 import net.sf.openrocket.rocketcomponent.FreeformFinSet;
30 import net.sf.openrocket.rocketcomponent.InnerTube;
31 import net.sf.openrocket.rocketcomponent.LaunchLug;
32 import net.sf.openrocket.rocketcomponent.MassObject;
33 import net.sf.openrocket.rocketcomponent.NoseCone;
34 import net.sf.openrocket.rocketcomponent.RadiusRingComponent;
35 import net.sf.openrocket.rocketcomponent.RingComponent;
36 import net.sf.openrocket.rocketcomponent.RocketComponent;
37 import net.sf.openrocket.rocketcomponent.Stage;
38 import net.sf.openrocket.rocketcomponent.Transition;
39 import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
40 import net.sf.openrocket.unit.Unit;
41 import net.sf.openrocket.unit.UnitGroup;
42 import net.sf.openrocket.util.Coordinate;
43
44 import javax.swing.ImageIcon;
45 import java.io.IOException;
46 import java.text.NumberFormat;
47 import java.util.Collection;
48 import java.util.Set;
49
50 /**
51  * A visitor strategy for creating documentation about parts details.
52  */
53 public class PartsDetailVisitorStrategy extends BaseVisitorStrategy {
54
55     /**
56      * The number of columns in the table.
57      */
58     private static final int TABLE_COLUMNS = 7;
59
60     /**
61      * The parts detail is represented as an iText table.
62      */
63     PdfPTable grid;
64
65     /**
66      * Construct a strategy for visiting a parts hierarchy for the purposes of collecting details on those parts.
67      *
68      * @param doc              The iText document
69      * @param theWriter        The direct iText writer
70      * @param theStagesToVisit The stages to be visited by this strategy
71      */
72     public PartsDetailVisitorStrategy (Document doc, PdfWriter theWriter, Set<Integer> theStagesToVisit) {
73         super(doc, theWriter, theStagesToVisit);
74         PrintUtilities.addText(doc, PrintUtilities.BIG_BOLD, "Parts Detail");
75     }
76
77     /**
78      * {@inheritDoc}
79      */
80     @Override
81     public void visit (final Stage visitable) {
82         try {
83             if (grid != null) {
84                 document.add(grid);
85             }
86             document.add(ITextHelper.createPhrase(visitable.getName()));
87             grid = new PdfPTable(TABLE_COLUMNS);
88             grid.setWidthPercentage(100);
89             grid.setHorizontalAlignment(Element.ALIGN_LEFT);
90         }
91         catch (DocumentException e) {
92         }
93
94         RocketComponent[] rc = visitable.getChildren();
95         goDeep(rc);
96     }
97
98
99     /**
100      * {@inheritDoc}
101      */
102     @Override
103     public void visit (final ExternalComponent visitable) {
104         grid.addCell(iconToImage(visitable));
105         grid.addCell(createNameCell(visitable.getName(), true));
106
107         grid.addCell(createMaterialCell(visitable.getMaterial()));
108         grid.addCell(ITextHelper.createCell());
109         grid.addCell(createLengthCell(visitable.getLength()));
110         grid.addCell(createMassCell(visitable.getMass()));
111
112         RocketComponent[] rc = visitable.getChildren();
113         goDeep(rc);
114     }
115
116     /**
117      * {@inheritDoc}
118      */
119     @Override
120     public void visit (final BodyComponent visitable) {
121         grid.addCell(visitable.getName());
122         grid.completeRow();
123         RocketComponent[] rc = visitable.getChildren();
124         goDeep(rc);
125     }
126
127     /**
128      * {@inheritDoc}
129      */
130     @Override
131     public void visit (final RingComponent visitable) {
132         grid.addCell(iconToImage(visitable));
133         grid.addCell(createNameCell(visitable.getName(), true));
134         grid.addCell(createMaterialCell(visitable.getMaterial()));
135         grid.addCell(createOuterDiaCell(visitable));
136         grid.addCell(createLengthCell(visitable.getLength()));
137         grid.addCell(createMassCell(visitable.getMass()));
138
139         RocketComponent[] rc = visitable.getChildren();
140         goDeep(rc);
141     }
142
143     /**
144      * {@inheritDoc}
145      */
146     @Override
147     public void visit (final InnerTube visitable) {
148         grid.addCell(iconToImage(visitable));
149         final PdfPCell pCell = createNameCell(visitable.getName(), true);
150         grid.addCell(pCell);
151         grid.addCell(createMaterialCell(visitable.getMaterial()));
152         grid.addCell(createOuterDiaCell(visitable));
153         grid.addCell(createLengthCell(visitable.getLength()));
154         grid.addCell(createMassCell(visitable.getMass()));
155
156         RocketComponent[] rc = visitable.getChildren();
157         goDeep(rc);
158     }
159
160     /**
161      * {@inheritDoc}
162      */
163     @Override
164     public void visit (final LaunchLug visitable) {
165         grid.addCell(iconToImage(visitable));
166         grid.addCell(createNameCell(visitable.getName(), true));
167
168         grid.addCell(createMaterialCell(visitable.getMaterial()));
169         grid.addCell(createOuterDiaCell(visitable));
170         grid.addCell(createLengthCell(visitable.getLength()));
171         grid.addCell(createMassCell(visitable.getMass()));
172     }
173
174     /**
175      * {@inheritDoc}
176      */
177     @Override
178     public void visit (final Transition visitable) {
179         grid.addCell(iconToImage(visitable));
180         grid.addCell(createNameCell(visitable.getName(), true));
181         grid.addCell(createMaterialCell(visitable.getMaterial()));
182
183         Chunk fore = new Chunk("Fore Dia: " + appendLength(visitable.getForeRadius() * 2));
184         fore.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
185         Chunk aft = new Chunk("Aft Dia: " + appendLength(visitable.getAftRadius() * 2));
186         aft.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
187         final PdfPCell cell = ITextHelper.createCell();
188         cell.addElement(fore);
189         cell.addElement(aft);
190         grid.addCell(cell);
191         grid.addCell(createLengthCell(visitable.getLength()));
192         grid.addCell(createMassCell(visitable.getMass()));
193
194         RocketComponent[] rc = visitable.getChildren();
195         goDeep(rc);
196     }
197
198     /**
199      * {@inheritDoc}
200      */
201     @Override
202     public void visit (final RadiusRingComponent visitable) {
203         grid.addCell(iconToImage(visitable));
204         grid.addCell(createNameCell(visitable.getName(), true));
205         grid.addCell(createMaterialCell(visitable.getMaterial()));
206         grid.addCell(createOuterDiaCell(visitable));
207         grid.addCell(createLengthCell(visitable.getLength()));
208         grid.addCell(createMassCell(visitable.getMass()));
209         RocketComponent[] rc = visitable.getChildren();
210         goDeep(rc);
211     }
212
213     /**
214      * {@inheritDoc}
215      */
216     @Override
217     public void visit (final MassObject visitable) {
218         PdfPCell cell = ITextHelper.createCell();
219         cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
220         cell.setPaddingBottom(12f);
221
222         grid.addCell(iconToImage(visitable));
223         final PdfPCell nameCell = createNameCell(visitable.getName(), true);
224         nameCell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
225         nameCell.setPaddingBottom(12f);
226         grid.addCell(nameCell);
227         grid.addCell(cell);
228         grid.addCell(cell);
229         grid.addCell(cell);
230         grid.addCell(createMassCell(visitable.getMass()));
231         RocketComponent[] rc = visitable.getChildren();
232         goDeep(rc);
233     }
234
235     /**
236      * {@inheritDoc}
237      */
238     @Override
239     public void visit (final NoseCone visitable) {
240         grid.addCell(iconToImage(visitable));
241         grid.addCell(createNameCell(visitable.getName(), true));
242         grid.addCell(createMaterialCell(visitable.getMaterial()));
243         grid.addCell(ITextHelper.createCell(visitable.getType().getName(), PdfPCell.BOTTOM));
244         grid.addCell(createLengthCell(visitable.getLength()));
245         grid.addCell(createMassCell(visitable.getMass()));
246         RocketComponent[] rc = visitable.getChildren();
247         goDeep(rc);
248     }
249
250     /**
251      * {@inheritDoc}
252      */
253     @Override
254     public void visit (final BodyTube visitable) {
255         grid.addCell(iconToImage(visitable));
256         grid.addCell(createNameCell(visitable.getName(), true));
257         grid.addCell(createMaterialCell(visitable.getMaterial()));
258         grid.addCell(createOuterDiaCell(visitable));
259         grid.addCell(createLengthCell(visitable.getLength()));
260         grid.addCell(createMassCell(visitable.getMass()));
261         RocketComponent[] rc = visitable.getChildren();
262         goDeep(rc);
263     }
264
265     /**
266      * {@inheritDoc}
267      */
268     @Override
269     public void visit (final TrapezoidFinSet visitable) {
270         visitFins(visitable);
271     }
272
273     /**
274      * {@inheritDoc}
275      */
276     @Override
277     public void visit (final EllipticalFinSet visitable) {
278         visitFins(visitable);
279     }
280
281     /**
282      * {@inheritDoc}
283      */
284     @Override
285     public void visit (final FreeformFinSet visitable) {
286         visitFins(visitable);
287     }
288
289     /**
290      * {@inheritDoc}
291      */
292     @Override
293     public void close () {
294         try {
295             if (grid != null) {
296                 document.add(grid);
297             }
298         }
299         catch (DocumentException e) {
300             e.printStackTrace();
301         }
302     }
303
304     private PdfPCell createOuterDiaCell (final Coaxial visitable) {
305         PdfPCell result = new PdfPCell();
306         Phrase p = new Phrase();
307         p.setLeading(12f);
308         result.setVerticalAlignment(Element.ALIGN_TOP);
309         result.setBorder(Rectangle.BOTTOM);
310         Chunk c = new Chunk();
311         c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
312         c.append("Dia");
313         p.add(c);
314
315         c = new Chunk();
316         c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.SMALL_FONT_SIZE));
317         c.append("out");
318         p.add(c);
319
320         c = new Chunk();
321         c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
322         c.append(" " + appendLength(visitable.getOuterRadius() * 2));
323         p.add(c);
324         createInnerDiaCell(visitable, result);
325         result.addElement(p);
326         return result;
327     }
328
329     private void createInnerDiaCell (final Coaxial visitable, PdfPCell cell) {
330         Phrase p = new Phrase();
331         p.setLeading(14f);
332         Chunk c = new Chunk();
333         c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
334         c.append("Dia");
335         p.add(c);
336
337         c = new Chunk();
338         c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.SMALL_FONT_SIZE));
339         c.append("in ");
340         p.add(c);
341
342         c = new Chunk();
343         c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
344         c.append("  " + appendLength(visitable.getInnerRadius() * 2));
345         p.add(c);
346         cell.addElement(p);
347     }
348
349     private void visitFins (FinSet visitable) {
350
351         Image img = null;
352         java.awt.Image awtImage = new PrintableFinSet(visitable).createImage();
353
354         Collection<Coordinate> x = visitable.getComponentBounds();
355
356         try {
357             img = Image.getInstance(writer, awtImage, 0.25f);
358         }
359         catch (BadElementException e) {
360             e.printStackTrace();
361         }
362         catch (IOException e) {
363             e.printStackTrace();
364         }
365
366         grid.addCell(iconToImage(visitable));
367         grid.addCell(createNameCell(visitable.getName() + " (" + visitable.getFinCount() + ")", true));
368         grid.addCell(createMaterialCell(visitable.getMaterial()));
369         grid.addCell(ITextHelper.createCell("Thick: " + appendLength(visitable.getThickness()), PdfPCell.BOTTOM));
370         final PdfPCell pCell = new PdfPCell();
371         pCell.setBorder(Rectangle.BOTTOM);
372         pCell.addElement(img);
373
374         grid.addCell(ITextHelper.createCell());
375         grid.addCell(createMassCell(visitable.getMass()));
376
377         RocketComponent[] rc = visitable.getChildren();
378         goDeep(rc);
379     }
380
381     protected PdfPCell createLengthCell (double length) {
382         return ITextHelper.createCell("Len: " + appendLength(length), PdfPCell.BOTTOM);
383     }
384
385     protected PdfPCell createMassCell (double mass) {
386         return ITextHelper.createCell("Mass: " + appendMass(mass), PdfPCell.BOTTOM);
387     }
388
389     protected PdfPCell createNameCell (String v, boolean withIndent) {
390         PdfPCell result = new PdfPCell();
391         result.setBorder(Rectangle.BOTTOM);
392         Chunk c = new Chunk();
393         c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
394         if (withIndent) {
395             for (int x = 0; x < (level - 2) * 10; x++) {
396                 c.append(" ");
397             }
398         }
399         c.append(v);
400         result.setColspan(2);
401         result.addElement(c);
402         return result;
403     }
404
405     protected PdfPCell createMaterialCell (Material material) {
406         PdfPCell cell = ITextHelper.createCell();
407         cell.setLeading(13f, 0);
408
409         Chunk c = new Chunk();
410         c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
411         c.append(appendMaterial(material));
412         cell.addElement(c);
413         Chunk density = new Chunk();
414         density.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.SMALL_FONT_SIZE));
415         density.append(appendMaterialDensity(material));
416         cell.addElement(density);
417         return cell;
418     }
419
420     protected PdfPCell iconToImage (final RocketComponent visitable) {
421         final ImageIcon icon = (ImageIcon) ComponentIcons.getLargeIcon(visitable.getClass());
422         try {
423             Image im = Image.getInstance(icon.getImage(), null);
424             im.scaleToFit(icon.getIconWidth() * 0.6f, icon.getIconHeight() * 0.6f);
425             PdfPCell cell = new PdfPCell(im);
426             cell.setFixedHeight(icon.getIconHeight() * 0.6f);
427             cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
428             cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
429             cell.setBorder(PdfPCell.NO_BORDER);
430             return cell;
431         }
432         catch (BadElementException e) {
433         }
434         catch (IOException e) {
435         }
436         return null;
437     }
438
439     protected String appendLength (double length) {
440         final Unit defaultUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit();
441         return NumberFormat.getNumberInstance().format(defaultUnit.toUnit(length)) + defaultUnit.toString();
442     }
443
444     protected String appendMass (double mass) {
445         final Unit defaultUnit = UnitGroup.UNITS_MASS.getDefaultUnit();
446         return NumberFormat.getNumberInstance().format(defaultUnit.toUnit(mass)) + defaultUnit.toString();
447     }
448
449     protected String appendMaterial (Material material) {
450         return material.getName();
451     }
452
453     protected String appendMaterialDensity (Material material) {
454         return " (" + material.getType().getUnitGroup().getDefaultUnit().toStringUnit(material.getDensity()) + ")";
455     }
456
457 }