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

    // Implement free-hand movement of the given component.
    // This is assumed to be contained within a JLayeredPane.

class SwingMouseResponder implements MouseListener, MouseMotionListener {
    SwingMouseResponder(JComponent component){
        setComponent(component);
        // Listen for mouse events on the component.
        component.addMouseListener(this);
    }

        // The MouseListener methods.
    public void mousePressed(MouseEvent e){
        // Pick up the point and remember it.
        setLastMousePoint(e.getPoint());
        setMoving(true);

        // Bring it to the top of its layer.
        final JComponent c = getComponent();
        final JLayeredPane pane = (JLayeredPane) c.getParent();
        pane.setPosition(c,0);
    }

        // Complete the final movement and finish moving.
    public void mouseReleased(MouseEvent e){
        if(getMoving()){
            moveToPoint(e.getPoint());
            setMoving(false);
        }
    }

        // Respond to a double click.
        // If the component is in the highest layer, move it to the bottom,
        // otherwise move it up one layer.
    public void mouseClicked(MouseEvent e){
        if(e.getClickCount() > 1){
            final JComponent c = getComponent();
            final JLayeredPane pane = (JLayeredPane) c.getParent();
            final int layer = pane.getLayer(c);
            if(layer == pane.highestLayer()){
                // Place it at the bottom of the lowest layer.
                pane.setLayer(c,pane.lowestLayer());
            }
            else{
                // Place it topmost within the next layer up.
                pane.setLayer(c,layer+1,0);
            }
        }
    }

    public void mouseEntered(MouseEvent e){
        // Not interested in this event.
    }

    public void mouseExited(MouseEvent e){
        // Cancel any movement.
        setMoving(false);
    }

        // The MouseMotionListener methods
        // These will only be active if we are moving.
    public void mouseDragged(MouseEvent e){
        moveToPoint(e.getPoint());
    }

    public void mouseMoved(MouseEvent e){
        moveToPoint(e.getPoint());
    }

        // Move from the current point by the relative distance
        // from lastMousePoint to p2.
        // Make p2 the new lastMousePoint.
    protected void moveToPoint(Point p2){
        final Point p1 = getLastMousePoint();
        // Calculate the offset.
        final int xdiff = p2.x-p1.x, ydiff = p2.y-p1.y;
        // Apply it to the component's current position.
        final JComponent c = getComponent();
        final Point loc = c.getLocation();
        loc.x += xdiff;
        loc.y += ydiff;
        c.setLocation(loc);
    }

    protected JComponent getComponent(){
        return component;
    }

    protected void setComponent(JComponent c){
         component = c;
    }

    protected boolean getMoving(){
        return moving;
    }

        // Make sure this represents a change of state.
        // Changing the state requires that we either listen
        // for mouse motion events, or stop doing so.
    protected void setMoving(boolean m){
        if(m != moving){
            final JComponent c = getComponent();
            if(m){
                c.addMouseMotionListener(this);
            }
            else{
                c.removeMouseMotionListener(this);
            }
            moving = m;
        }
    }

    protected Point getLastMousePoint(){
        return lastMousePoint;
    }

    protected void setLastMousePoint(Point p){
        lastMousePoint = p;
    }

    // Are we moving at the moment?
    private boolean moving = false;
    // Where the mouse last moved to.
    Point lastMousePoint;
    // The component to be moved.
    private JComponent component;
}
