import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.image.*;

public class AlphaView extends JPanel {
    Rectangle rect;
    Point2D.Double anchor;
    int side = 10;
    boolean moving = false;
    DisplayPixels display;
    boolean antialiasing = false;
    int offsetX, offsetY;

    public AlphaView(boolean b) {
	antialiasing = b;
        anchor = new Point2D.Double(95, 95);
        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent me) {
                if (rect.contains(me.getX(), me.getY()))
                    moving = true;
		offsetX = me.getX() - rect.x;
		offsetY = me.getY() - rect.y;
            }
            public void mouseReleased(MouseEvent me) {
                if (moving) moveTo(me.getX()-offsetX, me.getY()-offsetY);
                moving = false;
            }
        });

        addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseDragged(MouseEvent me) {
                if (moving) moveTo(me.getX()-offsetX, me.getY()-offsetY);
            }
        });
    }

    public void addDisplay(DisplayPixels d) {
        display = d;
        display.update((int)anchor.x, (int)anchor.y);
    }
    
    public void paintComponent(Graphics gfx) {
        setBackground(Color.white);
        super.paintComponent(gfx);
        Graphics2D g = (Graphics2D) gfx;
        drawBackground(g);
        rect = new Rectangle((int)anchor.x, (int) anchor.y, side, side);
	g.draw(rect);
    }

    public void drawBackground(Graphics2D g) {
	if (antialiasing) 
	    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
			       RenderingHints.VALUE_ANTIALIAS_ON);

	g.setPaint(Color.white);
	Rectangle bounds = getBounds();
	g.fillRect(0, 0, bounds.width, bounds.height);
	g.setPaint(Color.black);
        Point2D.Double p1 = new Point2D.Double(100, 150);
        Point2D.Double p2 = new Point2D.Double(170, 180);

        double r = p1.distance(p2);
        Ellipse2D.Double circle1 =
            new Ellipse2D.Double(p1.x - r, p1.y - r, 2*r, 2*r);
        Ellipse2D.Double circle2 =
            new Ellipse2D.Double(p2.x - r, p2.y - r, 2*r, 2*r);

        double u = p2.x - p1.x;  double v = p2.y - p1.y;
        double c = Math.cos(Math.PI/3);  double s = Math.sin(Math.PI/3);
        double ix = c * u - s * v + p1.x;  double iy = s * u + c * v + p1.y;
        Point2D.Double intersection = new Point2D.Double(ix, iy);

        Line2D.Double line1 = new Line2D.Double(p1, p2);
        Line2D.Double line2 = new Line2D.Double(p1, intersection);
        Line2D.Double line3 = new Line2D.Double(p2, intersection);

        g.draw(circle1);  g.draw(circle2);
        g.draw(line1);    g.draw(line2);    g.draw(line3);

        double size = 2;
        Ellipse2D.Double[] points = new Ellipse2D.Double[3];
        points[0] = getDot(p1);   points[1] = getDot(p2);
        points[2] = getDot(intersection);

        g.setPaint(new Color(0x33, 0x33, 0xcc));
        g.fill(points[0]);  g.fill(points[1]);
        g.setPaint(new Color(0xcc, 0x33, 0x33));
        g.fill(points[2]);

        g.setPaint(Color.black);
        for (int i = 0; i < 3;  i++) g.draw(points[i]);
    }

    public void moveTo(int x, int y) {
        anchor.setLocation(x, y);
        if (display != null) display.update(x, y);
        repaint();
    }

    public Ellipse2D.Double getDot(Point2D.Double p) {
        double size = 3;
        return new Ellipse2D.Double(p.x - size, p.y - size,
                                    2*size, 2*size);
    }

    public static void main(String[] args) {
	boolean antialiasing = false;
	try {
	    if (args[0].equals("on")) antialiasing = true;
	} catch(Exception ex) { }
        AlphaView view = new AlphaView(antialiasing);
        view.setPreferredSize(new Dimension(300, 300));
        JPEGDrawFrame frame = new JPEGDrawFrame("AlphaView");
        DisplayPixels dplay = new DisplayPixels(view, DisplayPixels.COLOR);
        view.addDisplay(dplay);
        dplay.setPreferredSize(new Dimension(151, 151));
        frame.getContentPane().add(view, BorderLayout.CENTER);
	JPanel bottom = new JPanel();
	bottom.add(dplay);
	bottom.setBackground(Color.white);
        frame.getContentPane().add(bottom, BorderLayout.SOUTH);
        frame.pack();
        frame.show();
    }

}
        
class DisplayPixels extends JPanel {
    static final int VALUE = 0;
    static final int COLOR = 1;
    int mode = VALUE;
    double side = 10;
    AlphaView view;
    BufferedImage bi;
    int dim = 15;
    int x, y;
    
    public DisplayPixels(AlphaView view, int m) {
        this.view = view;  mode = m;
        setBackground(Color.white);
    }
    
    public void update(int x, int y) {
        this.x = x;  this.y = y;
        repaint();
    }
    
    public void paintComponent(Graphics gfx) {
	//        super.paintComponent(gfx);
        Graphics2D g = (Graphics2D) gfx;
        if (bi == null) {
            bi = (BufferedImage) view.createImage(view.getWidth(),
                                                  view.getHeight());
            view.drawBackground((Graphics2D) bi.getGraphics());
        }
        for (int i = 0; i <= side; i++) {
            for (int j = 0; j <= side; j++) {
                int rgb = bi.getRGB(x+i, y+j);
                g.setPaint(new Color(rgb, true));
                g.fill(new Rectangle2D.Double(i*dim, j*dim, dim, dim));
            }
        }
	g.setPaint(Color.black);
	Rectangle r = getBounds();
	g.drawRect(0, 0, r.width-1, r.height-1);
    }
}

        
                                         
