create changelog entry
[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, with 1/2", 1/4", and 1/8" tick marks.
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             //Draw cm (10mm) and 1/2 cm (5mm) marks
84             drawVerticalRule(g2, false, !inchOutSide, x, y, width, 0, 0, div * 5, div * 10);
85             drawHorizontalRule(g2, true, !inchOutSide, x, y + width, width, 0, 0, div * 5, div * 10);
86         }
87     }
88
89     /**
90      * Draw a horizontal ruler.
91      *
92      * @param g              the graphics context
93      * @param vertexAtLeft   true if the horizontal/vertical vertex is oriented to the top
94      * @param drawTicksDown  true if the ruler should draw interval tick marks to the underside of the solid ruler line
95      * @param x              starting x position of the ruler
96      * @param y              starting y position of the rule
97      * @param length         the number of points in length to extend the vertical ruler
98      * @param tinyEveryX     the number of points for each tiny division tick line; if zero or negative tiny will not be
99      *                       drawn
100      * @param minorEveryX    the number of points for each minor division tick line; if zero or negative minor will not
101      *                       be drawn
102      * @param midMajorEveryX the number of points for each mid-major division tick line
103      * @param majorEveryX    the number of points for each major division tick line (this is typically the inch or cm
104      *                       distance in points).
105      */
106     private void drawHorizontalRule(Graphics2D g,
107                                    boolean vertexAtLeft,
108                                    boolean drawTicksDown,
109                                    int x, int y, int length,
110                                    double tinyEveryX,
111                                    double minorEveryX,
112                                    double midMajorEveryX,
113                                    double majorEveryX) {
114
115         //Draw solid horizontal line
116         g.setColor(Color.black);
117         g.drawLine(x, y, x + length, y);
118
119         int tiniest = drawTicksDown ? TINIEST_TICK_LENGTH : -1 * TINIEST_TICK_LENGTH;
120         int minor = drawTicksDown ? MINOR_TICK_LENGTH : -1 * MINOR_TICK_LENGTH;
121         int mid = drawTicksDown ? MID_MAJOR_TICK_LENGTH : -1 * MID_MAJOR_TICK_LENGTH;
122         int major = drawTicksDown ? MAJOR_TICK_LENGTH : -1 * MAJOR_TICK_LENGTH;
123
124         //Draw vertical rule ticks for the horizontal ruler
125         //Draw minor ticks
126         int initial = x;
127         int end = initial + length;
128         double increment = tinyEveryX;
129         boolean lessThanEqual = true;
130         if (!vertexAtLeft) {
131             initial = x + length;
132             end = x;
133             lessThanEqual = false;
134         }
135
136         if (tinyEveryX > 0) {
137             if (!vertexAtLeft) {
138                 increment = -1 * increment;
139             }
140             for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
141                 g.drawLine((int) xtick, y, (int) xtick, y + tiniest);
142             }
143         }
144         //Draw minor ticks
145         if (minorEveryX > 0) {
146             if (!vertexAtLeft) {
147                 increment = -1 * minorEveryX;
148             }
149             else {
150                 increment = minorEveryX;
151             }
152             for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
153                 g.drawLine((int) xtick, y, (int) xtick, y + minor);
154             }
155         }
156
157         //Draw mid-major ticks
158         if (midMajorEveryX > 0) {
159             if (!vertexAtLeft) {
160                 increment = -1 * midMajorEveryX;
161             }
162             else {
163                 increment = midMajorEveryX;
164             }
165             for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
166                 g.drawLine((int) xtick, y, (int) xtick, y + mid);
167             }
168         }
169         if (!vertexAtLeft) {
170             increment = -1 * majorEveryX;
171         }
172         else {
173             increment = majorEveryX;
174         }
175         //Draw major ticks
176         for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
177             g.drawLine((int) xtick, y, (int) xtick, y + major);
178         }
179
180     }
181
182     /**
183      * Draw a vertical ruler.
184      *
185      * @param g              the graphics context
186      * @param vertexAtTop    true if the horizontal/vertical vertex is oriented to the top
187      * @param drawTicksRight true if the ruler should draw interval tick marks to the right side of the solid ruler
188      *                       line
189      * @param x              starting x position of the ruler
190      * @param y              starting y position of the rule
191      * @param length         the number of points in length to extend the vertical ruler
192      * @param tinyEveryY     the number of points for each tiny division tick line; if zero or negative tiny will not be
193      *                       drawn
194      * @param minorEveryY    the number of points for each minor division tick line; if zero or negative minor will not
195      *                       be drawn
196      * @param midMajorEveryY the number of points for each mid-major division tick line
197      * @param majorEveryY    the number of points for each major division tick line (this is typically the inch or cm
198      *                       distance in points).
199      */
200     private void drawVerticalRule(Graphics2D g,
201                                  boolean vertexAtTop,
202                                  boolean drawTicksRight, int x, int y, int length,
203                                  double tinyEveryY,
204                                  double minorEveryY,
205                                  double midMajorEveryY,
206                                  double majorEveryY) {
207
208         int tiniest = drawTicksRight ? TINIEST_TICK_LENGTH : -1 * TINIEST_TICK_LENGTH;
209         int minor = drawTicksRight ? MINOR_TICK_LENGTH : -1 * MINOR_TICK_LENGTH;
210         int mid = drawTicksRight ? MID_MAJOR_TICK_LENGTH : -1 * MID_MAJOR_TICK_LENGTH;
211         int major = drawTicksRight ? MAJOR_TICK_LENGTH : -1 * MAJOR_TICK_LENGTH;
212
213         //Draw solid vertical line
214         g.setColor(Color.black);
215         g.drawLine(x, y, x, y + length);
216
217         //Draw horizontal rule ticks for the vertical ruler
218         //Draw tiny ticks
219         int initial = y;
220         int end = initial + length;
221         double increment = tinyEveryY;
222         boolean lessThanEqual = true;
223         if (!vertexAtTop) {
224             initial = y + length;
225             end = y;
226             lessThanEqual = false;
227         }
228
229         if (tinyEveryY > 0) {
230             if (!vertexAtTop) {
231                 increment = -1 * increment;
232             }
233             for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
234                 g.drawLine(x, (int) tick, x - tiniest, (int) tick);
235             }
236         }
237
238         //Draw minor ticks
239         if (minorEveryY > 0) {
240             if (!vertexAtTop) {
241                 increment = -1 * minorEveryY;
242             }
243             else {
244                 increment = minorEveryY;
245             }
246             for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
247                 g.drawLine(x, (int) tick, x - minor, (int) tick);
248             }
249         }
250
251         //Draw mid-major ticks
252         if (!vertexAtTop) {
253             increment = -1 * midMajorEveryY;
254         }
255         else {
256             increment = midMajorEveryY;
257         }
258         for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
259             g.drawLine(x, (int) tick, x - mid, (int) tick);
260         }
261
262         //Draw major ticks
263         if (!vertexAtTop) {
264             increment = -1 * majorEveryY;
265         }
266         else {
267             increment = majorEveryY;
268         }
269         for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
270             g.drawLine(x, (int) tick, x - major, (int) tick);
271         }
272
273     }
274 }