import java.awt.*;
import javax.swing.*;

public class Rule extends JComponent {

    public static final int INCH = Toolkit.getDefaultToolkit().getScreenResolution();
    public static final int HORIZONTAL = 0;
    public static final int VERTICAL = 1;
    public static final int SIZE = 35;

    public int orientation;
    public boolean isMetric;
    private int increment;
    private int units;

    public Rule(int o, boolean m) {
        orientation = o;
	isMetric = m;
	setIncrementAndUnits();
    }

    public void setIsMetric(boolean isMetric) {
	this.isMetric = isMetric;
	setIncrementAndUnits();
	repaint();
    }

    private void setIncrementAndUnits() {
	if (isMetric) {
	    units = (int)((double)INCH / (double)2.54); // dots per centimeter
	    increment = units;
	} else {
	    units = INCH;
	    increment = units / 2;
	}
    }

    public boolean isMetric() {
        return this.isMetric;
    }

    public int getIncrement() {
	return increment;
    }

    public void setPreferredHeight(int ph) {
	setPreferredSize(new Dimension(SIZE, ph));
    }

    public void setPreferredWidth(int pw) {
	setPreferredSize(new Dimension(pw, SIZE));
    }

    public void paintComponent(Graphics g) {

	Rectangle drawHere = g.getClipBounds();

	//fill clipping area with dirty brown/orange
	g.setColor(new Color(230, 163, 4));
	g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height);

	//do the ruler labels in a small font that's black
	g.setFont(new Font("SansSerif", Font.PLAIN, 10)); 
	g.setColor(Color.black);

	//some vars we need
        int end = 0;
        int start = 0;
        int tickLength = 0;
	String text = null;
    
	// use clipping bounds to calculate first tick and last tick location
        if (orientation == HORIZONTAL) {
	    start = (drawHere.x / increment) * increment;
	    end = (((drawHere.x + drawHere.width) / increment) + 1) * increment;
        } else {
	    start = (drawHere.y / increment) * increment;
	    end = (((drawHere.y + drawHere.height) / increment) + 1) * increment;
	}

	//Make a special case of 0 to display the number
	//within the rule and draw a units label
	if (start == 0) {
            text = Integer.toString(0) + (isMetric ? " cm" : " in");
	    tickLength = 10;
	    if (orientation == HORIZONTAL) {
	        g.drawLine(0, SIZE-1, 0, SIZE-tickLength-1);
	        g.drawString(text, 2, 21);
	    } else {
	        g.drawLine(SIZE-1, 0, SIZE-tickLength-1, 0);
	        g.drawString(text, 9, 10);
	    }
	    text = null;
	    start = increment;
	}

	// ticks and labels
        for (int i = start; i < end; i += increment) {
	    if (i % units == 0)  {
		tickLength = 10;
		text = Integer.toString(i/units);
	    } else {
		tickLength = 7;
	        text = null;
	    }

	    if (tickLength != 0) { 
	        if (orientation == HORIZONTAL) {
	            g.drawLine(i, SIZE-1, i, SIZE-tickLength-1);
		    if (text != null)
	                g.drawString(text, i-3, 21);
	        } else {
	            g.drawLine(SIZE-1, i, SIZE-tickLength-1, i);
		    if (text != null)
	                g.drawString(text, 9, i+3);
	        }
	    }
        }
    }
}
