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

public class MovingPoints extends JPanel implements MouseListener,
MouseMotionListener {
    MoveablePoint[] p;
    MoveablePoint moving;
    Line2D.Float line;
    
    public MovingPoints() {
	setBackground(Color.white);
	p = new MoveablePoint[2];
	p[0] = new MoveablePoint(100, 100);
	p[1] = new MoveablePoint(200, 200);
	line = new Line2D.Float(p[0], p[1]);
	addMouseListener(this);
	addMouseMotionListener(this);
    }

    public void mouseClicked(MouseEvent me) { }
    public void mouseEntered(MouseEvent me) { }
    public void mouseExited(MouseEvent me) { }
    public void mouseMoved(MouseEvent me) { }

    public void mousePressed(MouseEvent me) {
	for (int i = 0; i < 2; i++) {
	    if (p[i].hit(me.getX(), me.getY())) {
		moving = p[i];  
		movePoint(me.getX(), me.getY());
		return;
	    }
	}
    }
    public void mouseReleased(MouseEvent me) {
	movePoint(me.getX(), me.getY());
	moving = null;
    }

    public void mouseDragged(MouseEvent me) {
	movePoint(me.getX(), me.getY());
    }    

    void movePoint(int x, int y) {
	if (moving == null) return;
	moving.setLocation(x, y);
	line.setLine(p[0].x, p[0].y, p[1].x, p[1].y);
	repaint();
    }

    public void paintComponent(Graphics gfx) {
	super.paintComponent(gfx);
	Graphics2D g = (Graphics2D) gfx;
	g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
			   RenderingHints.VALUE_ANTIALIAS_ON);
	g.setPaint(Color.blue);     g.draw(line);
	Shape s0 = p[0].getShape();   Shape s1 = p[1].getShape();
	g.setColor(Color.red);      g.fill(s0);  g.fill(s1);
	g.setColor(Color.black);    g.draw(s0);  g.draw(s1);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("MovingPoints");
	frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

	MovingPoints moving = new MovingPoints();
	moving.setPreferredSize(new Dimension(300, 300));
        frame.getContentPane().add(moving, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }

    class MoveablePoint extends Point2D.Float {
	int r = 3;
	Shape shape;
        public MoveablePoint(int x, int y) {
	    super(x, y);
	    setLocation(x, y);
	}

	void setLocation(int x, int y) {
	    super.setLocation(x, y);
	    shape = new Ellipse2D.Float(x - r, y - r, 2*r, 2*r);
	}

        public boolean hit(int x, int y) {
	    return shape.contains(x, y);
	}

        public Shape getShape() {
	    return shape;
	}
    }
	
}

	

    
