public class JJigsawPane extends JPanel {
private List<JigsawPiece> pieces = new ArrayList<JigsawPiece>();
private JigsawPiece floatingPiece = null;
private Point floatingFrom = null;
/** Creates a new {@code JJigsawPane}. */
public JJigsawPane() {
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
setFocusable(true);
}
/**
* Get the jigsaw piece at the given coordinates.
*
* @param x the X value of the point
* @param y the Y value of the point
* @return the jigsaw piece & possibly {@code null}
*/
public JigsawPiece getJigsawPieceAt(int x, int y) {
for (JigsawPiece piece : pieces) {
if (piece.getShape().contains(x, y)) {
return piece;
}
}
return null;
}
protected void moveFloatingJigsawPiece(MouseEvent e) {
final JigsawPiece piece = floatingPiece;
final Rectangle bounds = piece.getShape().getBounds();
piece.setLocation(bounds.x + floatingFrom.x - e.getX(), bounds.y
+ floatingFrom.y
- e.getY());
floatingFrom = e.getPoint();
final Rectangle newBounds = piece.getShape().getBounds();
repaint(bounds.union(newBounds));
}
@Override
protected void processMouseEvent(MouseEvent e) {
super.processMouseEvent(e);
final JigsawPiece piece;
if (e.getID() == MouseEvent.MOUSE_PRESSED
&& (piece = getJigsawPieceAt(e.getX(), e.getY())) != null) {
/* piece becomes floating */
floatingPiece = piece;
floatingFrom = e.getPoint();
repaint(piece.getShape().getBounds());
} else if (MouseEvent.MOUSE_RELEASED == e.getID()
&& floatingPiece != null) {
/* piece stops floating */
moveFloatingJigsawPiece(e);
floatingPiece = null;
repaint();
}
}
@Override
protected void processMouseMotionEvent(MouseEvent e) {
super.processMouseMotionEvent(e);
if (MouseEvent.MOUSE_DRAGGED == e.getID() && floatingPiece != null) {
moveFloatingJigsawPiece(e);
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D g2d = (Graphics2D) g;
for (JigsawPiece piece : pieces) {
/* paint all but the floating piece */
if (piece != floatingPiece) {
paintJigsawPiece(g2d, piece, true);
}
}
/* paint the floating piece on top */
if (floatingPiece != null) {
paintJigsawPiece(g2d, floatingPiece, true);
}
}
protected void paintJigsawPiece(
Graphics2D g2d,
JigsawPiece puzzleTile,
boolean isFloating) {
final Icon icon = puzzleTile.getIcon();
final Shape shape = puzzleTile.getShape();
final Rectangle bounds = shape.getBounds();
icon.paintIcon(this, g2d, bounds.x, bounds.y);
if (isFloating) {
g2d.setColor(Color.BLACK);
g2d.draw(shape);
}
}
}