Merge commit '42b2e5ca519766e37ce6941ba4faecc9691cc403' into upstream
[debian/openrocket] / core / src / net / sf / openrocket / gui / print / components / Rule.java
diff --git a/core/src/net/sf/openrocket/gui/print/components/Rule.java b/core/src/net/sf/openrocket/gui/print/components/Rule.java
new file mode 100644 (file)
index 0000000..b26d652
--- /dev/null
@@ -0,0 +1,274 @@
+package net.sf.openrocket.gui.print.components;
+
+import net.sf.openrocket.gui.print.PrintUnit;
+import net.sf.openrocket.gui.print.PrintableComponent;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+
+/**
+ * This class creates a Swing ruler.  The ruler has both vertical and horizontal rules, as well as divisions for both
+ * inches and centimeters.
+ */
+public class Rule extends PrintableComponent {
+
+    public static enum Orientation {
+        TOP,
+        BOTTOM
+    }
+
+    public static final int TINIEST_TICK_LENGTH = 3;
+    public static final int MINOR_TICK_LENGTH = 6;
+    public static final int MID_MAJOR_TICK_LENGTH = 9;
+    public static final int MAJOR_TICK_LENGTH = 14;
+
+    private Orientation orientation;
+
+    /**
+     * Constructor.
+     *
+     * @param theOrientation defines if the horizontal ruler should be on the top or bottom; the vertical is always
+     *                       left justified
+     */
+    public Rule(Orientation theOrientation) {
+        orientation = theOrientation;
+        int dim = (int) PrintUnit.INCHES.toPoints(2) + 32;
+        setSize(dim, dim);
+    }
+
+    /**
+     * Render the component onto a graphics context.
+     *
+     * @param g the opaque graphics context
+     */
+    public void paintComponent(Graphics g) {
+        Graphics2D g2 = (Graphics2D) g;
+
+        double div = PrintUnit.INCHES.toPoints(1) / 8;  //1/8 inch increment
+        final int width = (int) PrintUnit.INCHES.toPoints(2);
+        int x = 20;
+        int y = x + 20;
+        boolean inchOutSide = true;
+
+        g2.translate(getOffsetX(), getOffsetY());
+
+        if (orientation == Orientation.TOP) {
+            Font f = g.getFont();
+            g.setFont(f.deriveFont(f.getSize() - 2f));
+            g.drawString("in  cm", x - MAJOR_TICK_LENGTH, y + width + 20);
+            g.drawString("in", x + width + 4, y + 4);
+            g.drawString("cm", x + width + 4, y + 18);
+            y += 6;
+
+            drawVerticalRule(g2, true, inchOutSide, x, y, width, 0, div * 2, div * 4, div * 8);
+            drawHorizontalRule(g2, true, !inchOutSide, x, y, width, 0, div * 2, div * 4, div * 8);
+            div = PrintUnit.MILLIMETERS.toPoints(1);  //mm increment
+            drawVerticalRule(g2, true, !inchOutSide, x, y, width, 0, 0, div * 5, div * 10);
+            drawHorizontalRule(g2, true, inchOutSide, x, y, width, 0, 0, div * 5, div * 10);
+        }
+        else {
+            Font f = g.getFont();
+            g.setFont(f.deriveFont(f.getSize() - 2f));
+            g.drawString("in  cm", x - MAJOR_TICK_LENGTH, y);
+            g.drawString("cm", x + width + 6, y + width + 4);
+            g.drawString("in", x + width + 6, y + width + 18);
+            y += 6;
+
+            //Draw Inches first, with 1/2", 1/4", and 1/8" tick marks.
+            drawVerticalRule(g2, false, inchOutSide, x, y, width, 0, div * 2, div * 4, div * 8);
+            drawHorizontalRule(g2, true, inchOutSide, x, y + width, width, 0, div * 2, div * 4, div * 8);
+            div = PrintUnit.MILLIMETERS.toPoints(1);  //mm increment
+            //Draw cm (10mm) and 1/2 cm (5mm) marks
+            drawVerticalRule(g2, false, !inchOutSide, x, y, width, 0, 0, div * 5, div * 10);
+            drawHorizontalRule(g2, true, !inchOutSide, x, y + width, width, 0, 0, div * 5, div * 10);
+        }
+    }
+
+    /**
+     * Draw a horizontal ruler.
+     *
+     * @param g              the graphics context
+     * @param vertexAtLeft   true if the horizontal/vertical vertex is oriented to the top
+     * @param drawTicksDown  true if the ruler should draw interval tick marks to the underside of the solid ruler line
+     * @param x              starting x position of the ruler
+     * @param y              starting y position of the rule
+     * @param length         the number of points in length to extend the vertical ruler
+     * @param tinyEveryX     the number of points for each tiny division tick line; if zero or negative tiny will not be
+     *                       drawn
+     * @param minorEveryX    the number of points for each minor division tick line; if zero or negative minor will not
+     *                       be drawn
+     * @param midMajorEveryX the number of points for each mid-major division tick line
+     * @param majorEveryX    the number of points for each major division tick line (this is typically the inch or cm
+     *                       distance in points).
+     */
+    private void drawHorizontalRule(Graphics2D g,
+                                   boolean vertexAtLeft,
+                                   boolean drawTicksDown,
+                                   int x, int y, int length,
+                                   double tinyEveryX,
+                                   double minorEveryX,
+                                   double midMajorEveryX,
+                                   double majorEveryX) {
+
+        //Draw solid horizontal line
+        g.setColor(Color.black);
+        g.drawLine(x, y, x + length, y);
+
+        int tiniest = drawTicksDown ? TINIEST_TICK_LENGTH : -1 * TINIEST_TICK_LENGTH;
+        int minor = drawTicksDown ? MINOR_TICK_LENGTH : -1 * MINOR_TICK_LENGTH;
+        int mid = drawTicksDown ? MID_MAJOR_TICK_LENGTH : -1 * MID_MAJOR_TICK_LENGTH;
+        int major = drawTicksDown ? MAJOR_TICK_LENGTH : -1 * MAJOR_TICK_LENGTH;
+
+        //Draw vertical rule ticks for the horizontal ruler
+        //Draw minor ticks
+        int initial = x;
+        int end = initial + length;
+        double increment = tinyEveryX;
+        boolean lessThanEqual = true;
+        if (!vertexAtLeft) {
+            initial = x + length;
+            end = x;
+            lessThanEqual = false;
+        }
+
+        if (tinyEveryX > 0) {
+            if (!vertexAtLeft) {
+                increment = -1 * increment;
+            }
+            for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
+                g.drawLine((int) xtick, y, (int) xtick, y + tiniest);
+            }
+        }
+        //Draw minor ticks
+        if (minorEveryX > 0) {
+            if (!vertexAtLeft) {
+                increment = -1 * minorEveryX;
+            }
+            else {
+                increment = minorEveryX;
+            }
+            for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
+                g.drawLine((int) xtick, y, (int) xtick, y + minor);
+            }
+        }
+
+        //Draw mid-major ticks
+        if (midMajorEveryX > 0) {
+            if (!vertexAtLeft) {
+                increment = -1 * midMajorEveryX;
+            }
+            else {
+                increment = midMajorEveryX;
+            }
+            for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
+                g.drawLine((int) xtick, y, (int) xtick, y + mid);
+            }
+        }
+        if (!vertexAtLeft) {
+            increment = -1 * majorEveryX;
+        }
+        else {
+            increment = majorEveryX;
+        }
+        //Draw major ticks
+        for (double xtick = initial; lessThanEqual ? (xtick <= end) : (xtick >= end); xtick += increment) {
+            g.drawLine((int) xtick, y, (int) xtick, y + major);
+        }
+
+    }
+
+    /**
+     * Draw a vertical ruler.
+     *
+     * @param g              the graphics context
+     * @param vertexAtTop    true if the horizontal/vertical vertex is oriented to the top
+     * @param drawTicksRight true if the ruler should draw interval tick marks to the right side of the solid ruler
+     *                       line
+     * @param x              starting x position of the ruler
+     * @param y              starting y position of the rule
+     * @param length         the number of points in length to extend the vertical ruler
+     * @param tinyEveryY     the number of points for each tiny division tick line; if zero or negative tiny will not be
+     *                       drawn
+     * @param minorEveryY    the number of points for each minor division tick line; if zero or negative minor will not
+     *                       be drawn
+     * @param midMajorEveryY the number of points for each mid-major division tick line
+     * @param majorEveryY    the number of points for each major division tick line (this is typically the inch or cm
+     *                       distance in points).
+     */
+    private void drawVerticalRule(Graphics2D g,
+                                 boolean vertexAtTop,
+                                 boolean drawTicksRight, int x, int y, int length,
+                                 double tinyEveryY,
+                                 double minorEveryY,
+                                 double midMajorEveryY,
+                                 double majorEveryY) {
+
+        int tiniest = drawTicksRight ? TINIEST_TICK_LENGTH : -1 * TINIEST_TICK_LENGTH;
+        int minor = drawTicksRight ? MINOR_TICK_LENGTH : -1 * MINOR_TICK_LENGTH;
+        int mid = drawTicksRight ? MID_MAJOR_TICK_LENGTH : -1 * MID_MAJOR_TICK_LENGTH;
+        int major = drawTicksRight ? MAJOR_TICK_LENGTH : -1 * MAJOR_TICK_LENGTH;
+
+        //Draw solid vertical line
+        g.setColor(Color.black);
+        g.drawLine(x, y, x, y + length);
+
+        //Draw horizontal rule ticks for the vertical ruler
+        //Draw tiny ticks
+        int initial = y;
+        int end = initial + length;
+        double increment = tinyEveryY;
+        boolean lessThanEqual = true;
+        if (!vertexAtTop) {
+            initial = y + length;
+            end = y;
+            lessThanEqual = false;
+        }
+
+        if (tinyEveryY > 0) {
+            if (!vertexAtTop) {
+                increment = -1 * increment;
+            }
+            for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
+                g.drawLine(x, (int) tick, x - tiniest, (int) tick);
+            }
+        }
+
+        //Draw minor ticks
+        if (minorEveryY > 0) {
+            if (!vertexAtTop) {
+                increment = -1 * minorEveryY;
+            }
+            else {
+                increment = minorEveryY;
+            }
+            for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
+                g.drawLine(x, (int) tick, x - minor, (int) tick);
+            }
+        }
+
+        //Draw mid-major ticks
+        if (!vertexAtTop) {
+            increment = -1 * midMajorEveryY;
+        }
+        else {
+            increment = midMajorEveryY;
+        }
+        for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
+            g.drawLine(x, (int) tick, x - mid, (int) tick);
+        }
+
+        //Draw major ticks
+        if (!vertexAtTop) {
+            increment = -1 * majorEveryY;
+        }
+        else {
+            increment = majorEveryY;
+        }
+        for (double tick = initial; lessThanEqual ? (tick <= end) : (tick >= end); tick += increment) {
+            g.drawLine(x, (int) tick, x - major, (int) tick);
+        }
+
+    }
+}
\ No newline at end of file