Custom Layout Manager in Java (XYLayout)

Java
This year in my Advanced Java Programming class, I put an additional 'Ludo' game as semester project (it is suppose to use RMI).

My students who took the project wanted an easier layout manager to place the components (as I was quite against using null layout manager). So, they ask me whether there exists any XYLayout. It turns out there are some implementations out there, but I was not happy with their licenses. So, I ended up writing my own XYLayoutManager. It will be a good showcase for my students as well. Here goes the code:

/*
 *  The code is licensed under Create Commons Attribution 3.0 License
 *  http://creativecommons.org/licenses/by/3.0/
 *
 *  Copyright (c) 2010 Usman Saleem.
 *  http://usmans.info
 *
 */

package info.usmans;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * The XYLayout places components on x,y location
 *
 * @author usman
 */

public class XYLayout implements LayoutManager {

	/*
	 * This hash table will contain our components and their x,y location as
	 * constraints
	 */

	private Map components = new LinkedHashMap();

	// Register a component into a map
	// The name is the x,y location of the component. i.e. 10,20

	public void addLayoutComponent(String name, Component comp) {
		// parse name, which should be in int,int format
		if (name == null || name.trim().length() <= 0) {
			throw new IllegalArgumentException("Invalid constraint: " + name);
		}

		String[] location = name.split(",");

		if (location == null || location.length != 2) {
			throw new IllegalArgumentException("Invalid constraint: " + name);
		}

		int x = 0;
		int y = 0;

		try {
			x = Integer.parseInt(location[0]);
			y = Integer.parseInt(location[1]);
		} catch (NumberFormatException nfe) {
			throw new IllegalArgumentException("Invalid constraint: " + name);
		}

		components.put(comp, new XYLocation(x, y));
	}

	// Remove components from our map
	public void removeLayoutComponent(Component comp) {
		components.remove(comp);
	}

	public Dimension preferredLayoutSize(Container target) {
		return target.getPreferredSize();
	}

	// for now return preferredlayoutsize
	public Dimension minimumLayoutSize(Container parent) {
		return preferredLayoutSize(parent);
	}

	// place all components at its desired location
	public void layoutContainer(Container parent) {
		Insets insets = parent.getInsets();
		for (Component c : components.keySet()) {
			XYLocation location = components.get(c);
			Dimension dimension = c.getPreferredSize();
			c.setBounds(location.x + insets.left, location.y + insets.top,
			dimension.width, dimension.height);
		}
	}

	/*
	 * This class is a simple value object class to hold x and y location
	 */

	private class XYLocation {
		private int x;
		private int y;
		public XYLocation(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
}



Here is the test class.


/*
 *  The code is licensed under Create Commons Attribution 3.0 License
 *  http://creativecommons.org/licenses/by/3.0/
 *
 *  Copyright 2010 Usman Saleem.
 *  http://usmans.info
 *
 */

package info.usmans;

import java.awt.BorderLayout;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;

/**
* A Test application to test XY Layout.
* @author usman
*/

public class TestXYLayout extends JFrame implements ActionListener {

   private JLabel board = new JLabel(new ImageIcon(getClass().getResource("ludo1.gif")));

   private JLabel stimpy = new JLabel(new ImageIcon(getClass().getResource("stimpy.gif")));

   private JPanel panel = new JPanel();

   private JPanel bottom = new JPanel();

   private JButton moveButton = new JButton("Move");



    public void init() {

        setSize(560, 620);

        //add our panels in JFrame

        add(panel, BorderLayout.CENTER);

        add(bottom, BorderLayout.SOUTH );


        //add our button in bottom frame
        bottom.add(moveButton);
        moveButton.addActionListener(this);

        //set panel layout to XYLayout
        panel.setLayout(new XYLayout());
        panel.add("0,0",stimpy);
        panel.add("0,0",board);

        //draw our components on center panel
        drawComponents();

    }

    private void drawComponents() {
        panel.remove(board);
        panel.remove(stimpy);
        //calculate random x,y position
        int x = new Random().nextInt(this.getX()+this.getWidth());
        int y = new Random().nextInt(this.getY()+this.getHeight());

        panel.add(String.valueOf(x)+","+String.valueOf(y), stimpy);
        panel.add("0,0", board);

        panel.validate();

    }

    public void actionPerformed(ActionEvent e) {
        drawComponents();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                 TestXYLayout test = new TestXYLayout();
                 test.init();
                 test.setDefaultCloseOperation(TestXYLayout.EXIT_ON_CLOSE);
                 test.setResizable(false);
                 test.setVisible(true);
            }

        });

    }
}