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