create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / gui / print / PrintableFinSet.java
1 /*
2  * PrintableFinSet.java
3  */
4 package net.sf.openrocket.gui.print;
5
6 import net.sf.openrocket.rocketcomponent.FinSet;
7 import net.sf.openrocket.util.Coordinate;
8
9 import java.awt.Color;
10 import java.awt.Graphics;
11 import java.awt.Graphics2D;
12 import java.awt.Image;
13 import java.awt.geom.GeneralPath;
14 import java.awt.image.BufferedImage;
15
16 /**
17  * This class allows for a FinSet to be printable.  It does so by decorating an existing finset (which will not be
18  * modified) and rendering it within a JPanel.  The JPanel is not actually visualized on a display, but instead renders
19  * it to a print device.
20  */
21 public class PrintableFinSet extends PrintableComponent {
22
23     /**
24      * The object that represents the shape (outline) of the fin.  This gets drawn onto the Swing component.
25      */
26     protected GeneralPath polygon = null;
27
28     /**
29      * The minimum X coordinate.
30      */
31     private int minX = 0;
32     /**
33      * The minimum Y coordinate.
34      */
35     private int minY = 0;
36
37     /**
38      * Constructor.
39      *
40      * @param fs the finset to print
41      */
42     public PrintableFinSet (FinSet fs) {
43         this(fs.getFinPointsWithTab());
44     }
45
46     /**
47      * Construct a fin set from a set of points.
48      *
49      * @param points an array of points.
50      */
51     public PrintableFinSet (Coordinate[] points) {
52         init(points);
53     }
54
55     /**
56      * Initialize the fin set polygon and set the size of the component.
57      *
58      * @param points an array of points.
59      */
60     private void init (Coordinate[] points) {
61
62         polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, points.length);
63         polygon.moveTo(0, 0);
64
65         int maxX = 0;
66         int maxY = 0;
67
68         for (Coordinate point : points) {
69             final long x = (long)PrintUnit.METERS.toPoints(point.x);
70             final long y = (long)PrintUnit.METERS.toPoints(point.y);
71             minX = (int) Math.min(x, minX);
72             minY = (int) Math.min(y, minY);
73             maxX = (int) Math.max(x, maxX);
74             maxY = (int) Math.max(y, maxY);
75             polygon.lineTo(x, y);
76         }
77         polygon.closePath();
78
79         setSize(maxX - minX, maxY - minY);
80     }
81
82     /**
83      * Returns a generated image of the fin set.  May then be used wherever AWT images can be used, or converted to
84      * another image/picture format and used accordingly.
85      *
86      * @return an awt image of the fin set
87      */
88     public Image createImage () {
89         int width = getWidth();
90         int height = getHeight();
91         // Create a buffered image in which to draw
92         BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
93         // Create a graphics contents on the buffered image
94         Graphics2D g2d = bufferedImage.createGraphics();
95         // Draw graphics
96         g2d.setBackground(Color.white);
97         g2d.clearRect(0, 0, width, height);
98         paintComponent(g2d);
99         // Graphics context no longer needed so dispose it
100         g2d.dispose();
101         return bufferedImage;
102     }
103
104     /**
105      * Render the fin set onto the graphics context.  This is done by creating a GeneralPath component that follows the
106      * outline of the fin set coordinates to create a polygon, which is then drawn onto the graphics context.
107      * Through-the-wall fin tabs are supported if they are present.
108      *
109      * @param g the Java2D graphics context
110      */
111     @Override
112     public void paintComponent(Graphics g) {
113         Graphics2D g2d = (Graphics2D) g;
114
115         int x = 0;
116         int y = 0;
117
118         int marginX = this.getOffsetX();
119         int marginY = this.getOffsetY();
120
121         // The minimum X/Y can be negative (primarily only Y due to fin tabs; rarely (never) X, but protect both anyway).
122         if (minX < marginX) {
123             x = marginX + Math.abs(minX);
124         }
125         if (minY < marginY) {
126             y = marginY + Math.abs(minY);
127         }
128         // Reset the origin.
129         g2d.translate(x, y);
130         g2d.setPaint(TemplateProperties.getFillColor());
131         g2d.fill(polygon);
132         g2d.setPaint(TemplateProperties.getLineColor());
133         g2d.draw(polygon);
134     }
135 }