Merge commit '42b2e5ca519766e37ce6941ba4faecc9691cc403' into upstream
[debian/openrocket] / core / src / net / sf / openrocket / gui / print / visitor / PartsDetailVisitorStrategy.java
index cdeb9247c17742590137596438842d2892884c3f..c155d0cdef0ebc61b908ce2b0d1c529e96248518 100644 (file)
@@ -3,27 +3,54 @@
  */
 package net.sf.openrocket.gui.print.visitor;
 
-import com.itextpdf.text.*;
-import com.itextpdf.text.pdf.PdfPCell;
-import com.itextpdf.text.pdf.PdfPTable;
-import com.itextpdf.text.pdf.PdfWriter;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.ImageIcon;
+
 import net.sf.openrocket.gui.main.ComponentIcons;
 import net.sf.openrocket.gui.print.ITextHelper;
 import net.sf.openrocket.gui.print.PrintUtilities;
 import net.sf.openrocket.gui.print.PrintableFinSet;
 import net.sf.openrocket.logging.LogHelper;
 import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.*;
+import net.sf.openrocket.preset.ComponentPreset;
+import net.sf.openrocket.rocketcomponent.BodyComponent;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.Bulkhead;
+import net.sf.openrocket.rocketcomponent.Coaxial;
+import net.sf.openrocket.rocketcomponent.ExternalComponent;
+import net.sf.openrocket.rocketcomponent.FinSet;
+import net.sf.openrocket.rocketcomponent.InnerTube;
+import net.sf.openrocket.rocketcomponent.LaunchLug;
+import net.sf.openrocket.rocketcomponent.MassObject;
+import net.sf.openrocket.rocketcomponent.NoseCone;
+import net.sf.openrocket.rocketcomponent.Parachute;
+import net.sf.openrocket.rocketcomponent.RadiusRingComponent;
+import net.sf.openrocket.rocketcomponent.RecoveryDevice;
+import net.sf.openrocket.rocketcomponent.RingComponent;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.rocketcomponent.ShockCord;
+import net.sf.openrocket.rocketcomponent.Stage;
+import net.sf.openrocket.rocketcomponent.Streamer;
+import net.sf.openrocket.rocketcomponent.Transition;
 import net.sf.openrocket.startup.Application;
 import net.sf.openrocket.unit.Unit;
 import net.sf.openrocket.unit.UnitGroup;
-import net.sf.openrocket.util.Coordinate;
 
-import javax.swing.*;
-import java.text.NumberFormat;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
+import com.itextpdf.text.Chunk;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Element;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.Image;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.Phrase;
+import com.itextpdf.text.Rectangle;
+import com.itextpdf.text.pdf.PdfPCell;
+import com.itextpdf.text.pdf.PdfPTable;
+import com.itextpdf.text.pdf.PdfWriter;
+import com.itextpdf.text.pdf.draw.VerticalPositionMark;
 
 /**
  * A visitor strategy for creating documentation about parts details.
@@ -142,7 +169,7 @@ public class PartsDetailVisitorStrategy {
         else if (component instanceof LaunchLug) {
             LaunchLug ll = (LaunchLug) component;
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
 
             grid.addCell(createMaterialCell(ll.getMaterial()));
             grid.addCell(createOuterInnerDiaCell(ll));
@@ -152,7 +179,7 @@ public class PartsDetailVisitorStrategy {
         else if (component instanceof NoseCone) {
             NoseCone nc = (NoseCone) component;
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(nc.getMaterial()));
             grid.addCell(ITextHelper.createCell(nc.getType().getName(), PdfPCell.BOTTOM));
             grid.addCell(createLengthCell(component.getLength()));
@@ -163,13 +190,13 @@ public class PartsDetailVisitorStrategy {
         else if (component instanceof Transition) {
             Transition tran = (Transition) component;
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(tran.getMaterial()));
 
             Chunk fore = new Chunk(FORE_DIAMETER + toLength(tran.getForeRadius() * 2));
-            fore.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+            fore.setFont(PrintUtilities.NORMAL);
             Chunk aft = new Chunk(AFT_DIAMETER + toLength(tran.getAftRadius() * 2));
-            aft.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+            aft.setFont(PrintUtilities.NORMAL);
             final PdfPCell cell = ITextHelper.createCell();
             cell.addElement(fore);
             cell.addElement(aft);
@@ -183,7 +210,7 @@ public class PartsDetailVisitorStrategy {
         else if (component instanceof BodyTube) {
             BodyTube bt = (BodyTube) component;
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(bt.getMaterial()));
             grid.addCell(createOuterInnerDiaCell(bt));
             grid.addCell(createLengthCell(component.getLength()));
@@ -203,7 +230,7 @@ public class PartsDetailVisitorStrategy {
         else if (component instanceof ExternalComponent) {
             ExternalComponent ext = (ExternalComponent) component;
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
 
             grid.addCell(createMaterialCell(ext.getMaterial()));
             grid.addCell(ITextHelper.createCell());
@@ -216,7 +243,7 @@ public class PartsDetailVisitorStrategy {
         else if (component instanceof InnerTube) {
             InnerTube it = (InnerTube) component;
             grid.addCell(iconToImage(component));
-            final PdfPCell pCell = createNameCell(component.getName(), true);
+            final PdfPCell pCell = createNameCell(component.getName(), true, component.getPresetComponent());
             grid.addCell(pCell);
             grid.addCell(createMaterialCell(it.getMaterial()));
             grid.addCell(createOuterInnerDiaCell(it));
@@ -229,7 +256,7 @@ public class PartsDetailVisitorStrategy {
         else if (component instanceof RadiusRingComponent) {
             RadiusRingComponent rrc = (RadiusRingComponent) component;
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(rrc.getMaterial()));
             if (component instanceof Bulkhead) {
                 grid.addCell(createDiaCell(rrc.getOuterRadius()*2));
@@ -245,7 +272,7 @@ public class PartsDetailVisitorStrategy {
         else if (component instanceof RingComponent) {
             RingComponent ring = (RingComponent) component;
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(ring.getMaterial()));
             grid.addCell(createOuterInnerDiaCell(ring));
             grid.addCell(createLengthCell(component.getLength()));
@@ -260,7 +287,7 @@ public class PartsDetailVisitorStrategy {
             cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
             cell.setPaddingBottom(12f);
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(ring.getMaterial()));
             grid.addCell(cell);
             grid.addCell(createLengthCell(ring.getCordLength()));
@@ -272,14 +299,19 @@ public class PartsDetailVisitorStrategy {
             cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
             cell.setPaddingBottom(12f);
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(chute.getMaterial()));
+//            if (chute.hasSpillHole()) {
+//                grid.addCell(createOuterInnerDiaCell(chute.getDiameter()/2, chute.getSpillHoleDiameter()/2));
+//        }
+//        else {
             grid.addCell(createDiaCell(chute.getDiameter()));
+//        }
             grid.addCell(createLengthCell(component.getLength()));
             grid.addCell(createMassCell(component.getMass()));
 
             grid.addCell(iconToImage(null));
-            grid.addCell(createNameCell(SHROUD_LINES, true));
+            grid.addCell(createNameCell(SHROUD_LINES, true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(chute.getLineMaterial()));
             grid.addCell(createLinesCell(chute.getLineCount()));
             grid.addCell(createLengthCell(chute.getLineLength()));
@@ -291,7 +323,7 @@ public class PartsDetailVisitorStrategy {
             cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
             cell.setPaddingBottom(12f);
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(ring.getMaterial()));
             grid.addCell(createStrip(ring));
             grid.addCell(createLengthCell(component.getLength()));
@@ -303,7 +335,7 @@ public class PartsDetailVisitorStrategy {
             cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
             cell.setPaddingBottom(12f);
             grid.addCell(iconToImage(component));
-            grid.addCell(createNameCell(component.getName(), true));
+            grid.addCell(createNameCell(component.getName(), true, component.getPresetComponent()));
             grid.addCell(createMaterialCell(device.getMaterial()));
             grid.addCell(cell);
             grid.addCell(createLengthCell(component.getLength()));
@@ -315,7 +347,7 @@ public class PartsDetailVisitorStrategy {
             cell.setPaddingBottom(12f);
 
             grid.addCell(iconToImage(component));
-            final PdfPCell nameCell = createNameCell(component.getName(), true);
+            final PdfPCell nameCell = createNameCell(component.getName(), true, component.getPresetComponent());
             nameCell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
             nameCell.setPaddingBottom(12f);
             grid.addCell(nameCell);
@@ -355,17 +387,17 @@ public class PartsDetailVisitorStrategy {
         result.setVerticalAlignment(Element.ALIGN_TOP);
         result.setBorder(Rectangle.BOTTOM);
         Chunk c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
         c.append(DIAMETER);
         p.add(c);
 
         c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.SMALL_FONT_SIZE));
+        c.setFont(PrintUtilities.SMALL);
         c.append(OUTER);
         p.add(c);
 
         c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
         c.append(" " + toLength(diameter));
         p.add(c);
         result.addElement(p);
@@ -385,12 +417,12 @@ public class PartsDetailVisitorStrategy {
         result.setVerticalAlignment(Element.ALIGN_TOP);
         result.setBorder(Rectangle.BOTTOM);
         Chunk c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
         c.append(LENGTH);
         p.add(c);
 
         c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
         c.append(" " + toLength(component.getStripLength()));
         p.add(c);
         result.addElement(p);
@@ -398,12 +430,12 @@ public class PartsDetailVisitorStrategy {
         Phrase pw = new Phrase();
         pw.setLeading(14f);
         c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
         c.append(WIDTH);
         pw.add(c);
 
         c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
         c.append("  " + toLength(component.getStripWidth()));
         pw.add(c);
         result.addElement(pw);
@@ -415,29 +447,56 @@ public class PartsDetailVisitorStrategy {
      * Create a PDF cell that documents both an outer and an inner diameter of a component.
      *
      * @param component  a component that is a Coaxial
+     *
      * @return  the PDF cell that has the outer and inner diameters documented
      */
     private PdfPCell createOuterInnerDiaCell (final Coaxial component) {
+        return createOuterInnerDiaCell(component, INNER);
+    }
+
+    /**
+     * Create a PDF cell that documents both an outer and an inner diameter of a component.
+     *
+     * @param component  a component that is a Coaxial
+     * @param innerLabel the label to use for the inner label subscript
+     *
+     * @return  the PDF cell that has the outer and inner diameters documented
+     */
+    private PdfPCell createOuterInnerDiaCell (final Coaxial component, final String innerLabel) {
+        return createOuterInnerDiaCell(component.getOuterRadius(), component.getInnerRadius(), innerLabel);
+    }
+
+    /**
+     * Create a PDF cell that documents both an outer and an inner diameter of a component.
+     *
+     * @param outerRadius the outer radius
+     * @param innerRadius the inner radius
+     * @param innerLabel the label to use for the inner label subscript
+     *
+     * @return  the PDF cell that has the outer and inner diameters documented
+     */
+    private PdfPCell createOuterInnerDiaCell (final double outerRadius, final double innerRadius, final String innerLabel) {
+
         PdfPCell result = new PdfPCell();
         Phrase p = new Phrase();
         p.setLeading(12f);
         result.setVerticalAlignment(Element.ALIGN_TOP);
         result.setBorder(Rectangle.BOTTOM);
         Chunk c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
         c.append(DIAMETER);
         p.add(c);
 
         c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.SMALL_FONT_SIZE));
+        c.setFont(PrintUtilities.SMALL);
         c.append(OUTER);
         p.add(c);
 
         c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
-        c.append(" " + toLength(component.getOuterRadius() * 2));
+        c.setFont(PrintUtilities.NORMAL);
+        c.append(" " + toLength(outerRadius * 2));
         p.add(c);
-        createInnerDiaCell(component, result);
+        createInnerDiaCell(innerRadius, result, innerLabel);
         result.addElement(p);
         return result;
     }
@@ -445,25 +504,26 @@ public class PartsDetailVisitorStrategy {
     /**
      * Add inner diameter data to a cell.
      *
-     * @param component  a component that is a Coaxial
+     * @param innerRadius the inner radius
      * @param cell       the PDF cell to add the inner diameter data to
+     * @param innerLabel the label to use for the inner label subscript
      */
-    private void createInnerDiaCell (final Coaxial component, PdfPCell cell) {
+    private void createInnerDiaCell (final double innerRadius, PdfPCell cell, final String innerLabel) {
         Phrase p = new Phrase();
         p.setLeading(14f);
         Chunk c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
         c.append(DIAMETER);
         p.add(c);
 
         c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.SMALL_FONT_SIZE));
-        c.append(INNER);
+        c.setFont(PrintUtilities.SMALL);
+        c.append(innerLabel);
         p.add(c);
 
         c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
-        c.append("  " + toLength(component.getInnerRadius() * 2));
+        c.setFont(PrintUtilities.NORMAL);
+        c.append("  " + toLength(innerRadius * 2));
         p.add(c);
         cell.addElement(p);
     }
@@ -478,8 +538,6 @@ public class PartsDetailVisitorStrategy {
         Image img = null;
         java.awt.Image awtImage = new PrintableFinSet(theFinSet).createImage();
 
-        Collection<Coordinate> x = theFinSet.getComponentBounds();
-
         try {
             img = Image.getInstance(writer, awtImage, 0.25f);
         }
@@ -544,18 +602,49 @@ public class PartsDetailVisitorStrategy {
      * @return a PdfPCell that is formatted with the string <code>v</code>
      */
     protected PdfPCell createNameCell (String v, boolean withIndent) {
+        return createNameCell(v, withIndent, null);
+    }
+
+    /**
+     * Create a cell formatted for a name (or any string for that matter).
+     *
+     * @param v  the string to format into a PDF cell
+     * @param withIndent  if true, then an indention is made scaled to the level of the part in the parent hierarchy
+     * @param preset  the component's preset, if it has one
+     *
+     * @return a PdfPCell that is formatted with the string <code>v</code>
+     */
+    protected PdfPCell createNameCell (String v, boolean withIndent, ComponentPreset preset) {
         PdfPCell result = new PdfPCell();
+        result.setColspan(2);
         result.setBorder(Rectangle.BOTTOM);
+        Paragraph para = new Paragraph();
+        para.setLeading(12f, 0);
         Chunk c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
+        Chunk tab1 =
+          new Chunk(new VerticalPositionMark(), (level - 2) * 10, true);
+
         if (withIndent) {
-            for (int x = 0; x < (level - 2) * 10; x++) {
-                c.append(" ");
-            }
+            para.add(new Chunk(tab1));
         }
         c.append(v);
-        result.setColspan(2);
-        result.addElement(c);
+        para.add(c);
+
+        //Add the preset's manufacturer and part no in a subscript font.
+        if (preset != null) {
+            para.add(Chunk.NEWLINE);
+            c = new Chunk();
+            if (withIndent) {
+                para.add(new Chunk(tab1));
+            }
+            c.setFont(PrintUtilities.SMALL);
+            StringBuffer sb = new StringBuffer();
+            sb.append(preset.getManufacturer()).append(" ").append(preset.getPartNo());
+            c.append(sb.toString());
+            para.add(c);
+        }
+        result.addElement(para);
         return result;
     }
 
@@ -571,11 +660,11 @@ public class PartsDetailVisitorStrategy {
         cell.setLeading(13f, 0);
 
         Chunk c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(PrintUtilities.NORMAL);
         c.append(toMaterialName(material));
         cell.addElement(c);
         Chunk density = new Chunk();
-        density.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.SMALL_FONT_SIZE));
+        density.setFont(PrintUtilities.SMALL);
         density.append(toMaterialDensity(material));
         cell.addElement(density);
         return cell;
@@ -624,7 +713,7 @@ public class PartsDetailVisitorStrategy {
      */
     protected String toLength (double length) {
         final Unit defaultUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit();
-        return NumberFormat.getNumberInstance().format(defaultUnit.toUnit(length)) + defaultUnit.toString();
+        return defaultUnit.toStringUnit(length);
     }
 
     /**
@@ -636,7 +725,7 @@ public class PartsDetailVisitorStrategy {
      */
     protected String toMass (double mass) {
         final Unit defaultUnit = UnitGroup.UNITS_MASS.getDefaultUnit();
-        return NumberFormat.getNumberInstance().format(defaultUnit.toUnit(mass)) + defaultUnit.toString();
+        return defaultUnit.toStringUnit(mass);
     }
 
     /**