package jp.ac.osaka_u.sanken.util;

import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;

public class CheckableList extends JList {
	/**
	 *
	 */
	private static final long serialVersionUID = -8207275088256642406L;
	private CheckBoxCellRenderer renderer;

	public CheckableList() {
		this(new DefaultListModel());
	}

	public CheckableList(ListModel model) {
		super(model);
	}


	public void updateUI() {
		setForeground(null);
		setBackground(null);
		setSelectionForeground(null);
		setSelectionBackground(null);
		if(renderer!=null) {
			removeMouseListener(renderer);
			removeMouseMotionListener(renderer);
		}
		super.updateUI();
		renderer = new CheckBoxCellRenderer();
		setCellRenderer(renderer);
		addMouseListener(renderer);
		addMouseMotionListener(renderer);
	}
}

class CheckBoxCellRenderer extends JCheckBox implements ListCellRenderer, MouseListener, MouseMotionListener {
	/**
	 *
	 */
	private static final long serialVersionUID = 5134902478737266926L;
	private int rollOverRowIndex = -1;

	@Override
	public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
		this.setOpaque(true);
		if(isSelected) {
			this.setBackground(list.getSelectionBackground());
			this.setForeground(list.getSelectionForeground());
		}else{
			this.setBackground(list.getBackground());
			this.setForeground(list.getForeground());
		}
		if(value instanceof CheckableListItem) {
			this.setSelected(((CheckableListItem)value).selected);
			this.getModel().setRollover(index==rollOverRowIndex);
		}
		this.setText(value.toString());
		return this;
	}

	@Override
	public void mouseExited(MouseEvent e) {
		JList l = (JList)e.getSource();
		if(rollOverRowIndex>=0) {
			l.repaint(l.getCellBounds(rollOverRowIndex, rollOverRowIndex));
			rollOverRowIndex = -1;
		}
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		if(e.getButton()==MouseEvent.BUTTON1) {
			JList l = (JList)e.getComponent();
			DefaultListModel m = (DefaultListModel)l.getModel();
			Point p = e.getPoint();
			int index  = l.locationToIndex(p);
			if(index>=0) {
				CheckableListItem n = (CheckableListItem)m.get(index);
				m.set(index, new CheckableListItem(n.text, !n.selected));
				l.repaint(l.getCellBounds(index, index));
			}
		}
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		JList l = (JList)e.getSource();
		int index = l.locationToIndex(e.getPoint());
		if(index != rollOverRowIndex) {
			rollOverRowIndex = index;
			l.repaint();
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {}

	@Override
	public void mousePressed(MouseEvent e) {}

	@Override
	public void mouseReleased(MouseEvent e) {}

	@Override
	public void mouseDragged(MouseEvent e) {}
}

