Added ruler graphic to printed output; improvements to layout and margins in printing...
[debian/openrocket] / core / src / net / sf / openrocket / gui / print / components / Rule.java
1 package net.sf.openrocket.gui.print.components;
2
3 import net.sf.openrocket.gui.print.PrintUnit;
4 import net.sf.openrocket.gui.print.PrintableComponent;
5
6 import java.awt.Color;
7 import java.awt.Font;
8 import java.awt.Graphics;
9 import java.awt.Graphics2D;
10
11 /**
12  * This class creates a Swing ruler.  The ruler has both vertical and horizontal rules, as well as divisions for both
13  * inches and centimeters.
14  */
15 public class Rule extends PrintableComponent {
16
17     public static enum Orientation {
18         TOP,
19         BOTTOM
20     }
21
22     public static final int TINIEST_TICK_LENGTH = 3;
23     public static final int MINOR_TICK_LENGTH = 6;
24     public static final int MID_MAJOR_TICK_LENGTH = 9;
25     public static final int MAJOR_TICK_LENGTH = 14;
26
27     private Orientation orientation;
28
29     /**
30      * Constructor.
31      *
32      * @param theOrientation defines if the horizontal ruler should be on the top or bottom; the vertical is always
33      *                       left justified
34      */
35     public Rule(Orientation theOrientation) {
36         orientation = theOrientation;
37         int dim = (int) PrintUnit.INCHES.toPoints(2) + 32;
38         setSize(dim, dim);
39     }
40
41     /**
42      * Render the component onto a graphics context.
43      *
44      * @param g the opaque graphics context
45      */
46     public void paintComponent(Graphics g) {
47         Graphics2D g2 = (Graphics2D) g;
48
49         double div = PrintUnit.INCHES.toPoints(1) / 8;  //1/8 inch increment
50         final int width = (int) PrintUnit.INCHES.toPoints(2);
51         int x = 20;
52         int y = x + 20;
53         boolean inchOutSide = true;
54
55         g2.translate(getOffsetX(), getOffsetY());
56
57         if (orientation == Orientation.TOP) {
58             Font f = g.getFont();
59             g.setFont(f.deriveFont(f.getSize() - 2f));
60             g.drawString("in  cm", x - MAJOR_TICK_LENGTH, y + width + 20);
61             g.drawString("in", x + width + 4, y + 4);
62             g.drawString("cm", x + width + 4, y + 18);
63             y += 6;
64
65             drawVerticalRule(g2, true, inchOutSide, x, y, width, 0, div * 2, div * 4, div * 8);
66             drawHorizontalRule(g2, true, !inchOutSide, x, y, width, 0, div * 2, div * 4, div * 8);
67             div = PrintUnit.MILLIMETERS.toPoints(1);  //mm increment
68             drawVerticalRule(g2, true, !inchOutSide, x, y, width, 0, 0, div * 5, div * 10);
69             drawHorizontalRule(g2, true, inchOutSide, x, y, width, 0, 0, div * 5, div * 10);
70         }
71         else {
72             Font f = g.getFont();
73             g.setFont(f.deriveFont(f.getSize() - 2f));
74             g.drawString("in  cm", x - MAJOR_TICK_LENGTH, y);
75             g.drawString("cm", x + width + 6, y + width + 4);
76             g.drawString("in", x + width + 6, y + width + 18);
77             y += 6;
78
79             //Draw Inches first.
80             drawVerticalRule(g2, false, inchOutSide, x, y, width, 0, div * 2, div * 4, div * 8);
81             drawHorizontalRule(g2, true, inchOutSide, x, y + width, width, 0, div * 2, div * 4, div * 8);
82             div = PrintUnit.MILLIMETERS.toPoints(1);  //mm increment
83             drawVerticalRule(g2, false, !inchOutSide, x, y, width, 0, 0, div * 5, div * 10);
84             drawHorizontalRule(g2, true, !inchOutSide, x, y + width, width, 0, 0, div * 5, div * 10);
85         }
86     }
87
88     /**
89      * Draw a horizontal ruler.
90      *
91      * @param g              the graphics context
92      * @param vertexAtLeft   true if the horizontal/vertical vertex is oriented to the top
93      * @param drawTicksDown  true if the ruler should draw interval tick marks to the underside of the solid ruler line
94      * @param x              starting x position of the ruler
95      * @param y              starting y position of the rule
96      * @param length         the number of points in length to extend the vertical ruler
97      * @param tinyEveryX     the number of points for each tiny division tick line; if zero or negative tiny will not be
98      *                       drawn
99      * @param minorEveryX    the number of points for each minor division tick line; if zero or negative minor will not
100      *                       be drawn
101      * @param midMajorEveryX the number of points for each mid-major division tick line
102      * @param majorEveryX    the number of points for each major division tick line (this is typically the inch or cm
103      *                       distance in points).
104      */
105     private void drawHorizontalRule(Graphics2D g,
106                                    boolean vertexAtLeft,
107                                    boolean drawTicksDown,
108                                    int x, int y, int length,
109                                    double tinyEveryX,
110                                    double minorEveryX,
111                                    double midMajorEveryX,
112                                    double majorEveryX) {
113
114         //Draw solid horizontal line
115         g.setColor(Color.black);
116         g.drawLine(x, y, x + length, y);
117
118         int tiniest = drawTicksDown ? TINIEST_TICK_LENGTH : -1 * TINIEST_TICK_LENGTH;
119         int minor = drawTicksDown ? MINOR_TICK_LENGTH : -1 * MINOR_TICK_LENGTH;
120         int mid = drawTicksDown ? MID_MAJOR_TICK_LENGTH : -1 * MID_MAJOR_TICK_LENGTH;
121         int major = drawTicksDown ? MAJOR_TICK_LENGTH : -1 * MAJOR_TICK_LENGTH;
122
123         //Draw vertical rule ticks for the horizontal ruler
124         //Draw minor ticks
125         int initial = x;
126         int end = initial + length;
127         double increment = tinyEveryX;
128         boolean lessThanEqual = true;
129         if (!vertexAtLeft) {
130             initial = x + length;
131             end = x;
132             lessThanEqual = false;
133         }
134
135         if (tinyEveryX > 0) {
136             if (!vertexAtLeft) {
137                 increment = -1 * increment;
138             }
139             for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
140                 g.drawLine((int) xtick, y, (int) xtick, y + tiniest);
141             }
142         }
143         //Draw minor ticks
144         if (minorEveryX > 0) {
145             if (!vertexAtLeft) {
146                 increment = -1 * minorEveryX;
147             }
148             else {
149                 increment = minorEveryX;
150             }
151             for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
152                 g.drawLine((int) xtick, y, (int) xtick, y + minor);
153             }
154         }
155
156         //Draw mid-major ticks
157         if (midMajorEveryX > 0) {
158             if (!vertexAtLeft) {
159                 increment = -1 * midMajorEveryX;
160             }
161             else {
162                 increment = midMajorEveryX;
163             }
164             for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
165                 g.drawLine((int) xtick, y, (int) xtick, y + mid);
166             }
167         }
168         if (!vertexAtLeft) {
169             increment = -1 * majorEveryX;
170         }
171         else {
172             increment = majorEveryX;
173         }
174         //Draw major ticks
175         for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
176             g.drawLine((int) xtick, y, (int) xtick, y + major);
177         }
178
179     }
180
181     /**
182      * Draw a vertical ruler.
183      *
184      * @param g              the graphics context
185      * @param vertexAtTop    true if the horizontal/vertical vertex is oriented to the top
186      * @param drawTicksRight true if the ruler should draw interval tick marks to the right side of the solid ruler
187      *                       line
188      * @param x              starting x position of the ruler
189      * @param y              starting y position of the rule
190      * @param length         the number of points in length to extend the vertical ruler
191      * @param tinyEveryY     the number of points for each tiny division tick line; if zero or negative tiny will not be
192      *                       drawn
193      * @param minorEveryY    the number of points for each minor division tick line; if zero or negative minor will not
194      *                       be drawn
195      * @param midMajorEveryY the number of points for each mid-major division tick line
196      * @param majorEveryY    the number of points for each major division tick line (this is typically the inch or cm
197      *                       distance in points).
198      */
199     private void drawVerticalRule(Graphics2D g,
200                                  boolean vertexAtTop,
201                                  boolean drawTicksRight, int x, int y, int length,
202                                  double tinyEveryY,
203                                  double minorEveryY,
204                                  double midMajorEveryY,
205                                  double majorEveryY) {
206
207         int tiniest = drawTicksRight ? TINIEST_TICK_LENGTH : -1 * TINIEST_TICK_LENGTH;
208         int minor = drawTicksRight ? MINOR_TICK_LENGTH : -1 * MINOR_TICK_LENGTH;
209         int mid = drawTicksRight ? MID_MAJOR_TICK_LENGTH : -1 * MID_MAJOR_TICK_LENGTH;
210         int major = drawTicksRight ? MAJOR_TICK_LENGTH : -1 * MAJOR_TICK_LENGTH;
211
212         //Draw solid vertical line
213         g.setColor(Color.black);
214         g.drawLine(x, y, x, y + length);
215
216         //Draw horizontal rule ticks for the vertical ruler
217         //Draw tiny ticks
218         int initial = y;
219         int end = initial + length;
220         double increment = tinyEveryY;
221         boolean lessThanEqual = true;
222         if (!vertexAtTop) {
223             initial = y + length;
224             end = y;
225             lessThanEqual = false;
226         }
227
228         if (tinyEveryY > 0) {
229             if (!vertexAtTop) {
230                 increment = -1 * increment;
231             }
232             for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
233                 g.drawLine(x, (int) tick, x - tiniest, (int) tick);
234             }
235         }
236
237         //Draw minor ticks
238         if (minorEveryY > 0) {
239             if (!vertexAtTop) {
240                 increment = -1 * minorEveryY;
241             }
242             else {
243                 increment = minorEveryY;
244             }
245             for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
246                 g.drawLine(x, (int) tick, x - minor, (int) tick);
247             }
248         }
249
250         //Draw mid-major ticks
251         if (!vertexAtTop) {
252             increment = -1 * midMajorEveryY;
253         }
254         else {
255             increment = midMajorEveryY;
256         }
257         for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
258             g.drawLine(x, (int) tick, x - mid, (int) tick);
259         }
260
261         //Draw major ticks
262         if (!vertexAtTop) {
263             increment = -1 * majorEveryY;
264         }
265         else {
266             increment = majorEveryY;
267         }
268         for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
269             g.drawLine(x, (int) tick, x - major, (int) tick);
270         }
271
272     }
273 }