import java.awt.BasicStroke;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.GeneralPath;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Surface extends JPanel implements MouseMotionListener
{
    // current position of interactive cliping rectangle
    private int x = -1, y = -1;   
    // size of clipping rectangle
    private static final int RECTANGLE_SIZE = 50;
    
    public Surface ()
    {        
        // install mouse motion listener
        addMouseMotionListener(this);        
    }
    
    /**
     * Performs the drawing with the passed graphics context.
     * @param g  the graphics context to be used.
     */       
    private void doDrawing (Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g;
        
        // setup stroke        
        g2d.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));        
        // draw interactive rectangle representing clipping region
        if (x != -1 && y != -1)
        {
            g2d.drawRect(x - RECTANGLE_SIZE / 2, y - RECTANGLE_SIZE / 2,
                         RECTANGLE_SIZE, RECTANGLE_SIZE);
        }                
        // draw a simple line using the "old" API
        g2d.drawLine(30, 40, 200, 20);        
        // draw a simple line using the shape based API
        g2d.draw(new java.awt.geom.Line2D.Double(30.0d, 120.0d, 200.0d, 100.0d));        
        // draw a closed path consisting of a line and a curve        
        GeneralPath shape = new GeneralPath();
        shape.moveTo(250, 10);        
        shape.lineTo(400, 400);
        shape.curveTo(500, 5, 600, 600, 700, 7);
        shape.closePath();
        g2d.draw(shape);
    }

    @Override
    public void paintComponent (Graphics g)
    {        
        super.paintComponent(g);
        doDrawing(g);
    }

    @Override
    public void mouseDragged (MouseEvent e)
    {        
    }

    @Override
    public void mouseMoved (MouseEvent e)
    {
        Rectangle rect = new Rectangle(-1, -1);
        
        // build rectangle of previous position
        if (x != -1 && y != -1)
        {
            rect.add(new Rectangle(x - RECTANGLE_SIZE / 2, y - RECTANGLE_SIZE / 2,
                                   RECTANGLE_SIZE, RECTANGLE_SIZE));
        }        
        // add rectangle of new position
        if (e != null)
        {
            x = e.getX();
            y = e.getY();
            rect.add(new Rectangle(x - RECTANGLE_SIZE / 2, y - RECTANGLE_SIZE / 2,
                                   RECTANGLE_SIZE, RECTANGLE_SIZE));
        }
        // grow rectangle by 1 pixel
        rect.grow(1, 1);
        // redraw dirty region
        repaint(rect);
    }
}

public class ClippingProblem extends JFrame
{
    public ClippingProblem ()
    {
        initUI();
    }

    private void initUI ()
    {

        add(new Surface());

        setTitle("Clipping Problems");
        setSize(750, 500);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
    }

    public static void main (String[] args)
    {

        EventQueue.invokeLater(new Runnable()
        {
            @Override
            public void run ()
            {
                ClippingProblem ex = new ClippingProblem();
                ex.setVisible(true);
            }
        });
    }
}
