// CommonDataTable.java
//
// Created: November 2005
//
// This file is a component of the BioMoby project.
// Copyright Martin Senger (martin.senger@gmail.com).
//

package org.biomoby.service.dashboard;

import org.tulsoft.tools.gui.SwingUtils;

import org.biomoby.shared.MobyData;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JComponent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.JTableHeader;
import javax.swing.AbstractCellEditor;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;

import java.util.Vector;

/**
 * A common parent to various swing JTables used for collecting
 * definitions of data (input or ouput) for a service. Used in the
 * service registration. <p>
 *
 * @author <A HREF="mailto:martin.senger@gmail.com">Martin Senger</A>
 * @version $Id: CommonDataTable.java,v 1.8 2006/04/28 00:13:41 senger Exp $
 */

public class CommonDataTable
    extends JTable {

    private static org.apache.commons.logging.Log log =
       org.apache.commons.logging.LogFactory.getLog (CommonDataTable.class);

    // indeces of the used columns
    public final static int COL_BUTTON = 0;

    // table model
    protected CommonDataTableModel tableModel;

    // shared icons
    protected static Icon deleteDataIcon, trashIcon, tAreaIcon;

    /*********************************************************************
     * Default constructor.
     ********************************************************************/
    protected CommonDataTable() {
	super();
	putClientProperty ("terminateEditOnFocusLost", Boolean.TRUE); 
    }

    /*********************************************************************
     * Another constructor.
     ********************************************************************/
    public CommonDataTable (CommonDataTableModel model) {
	super (model);
	tableModel = model;
	setModel (tableModel);
	createItself();
	putClientProperty ("terminateEditOnFocusLost", Boolean.TRUE); 
    }

    /*********************************************************************
     *
     ********************************************************************/
    public void addEmptyData() {
	tableModel.addEmptyData();
	int rowCount = getRowCount();
	clearSelection();
	addRowSelectionInterval (rowCount-1, rowCount-1);
    }

    /*********************************************************************
     *
     ********************************************************************/
    public void setData (MobyData[] newData) {
	tableModel.setData (newData);
    }

    /*********************************************************************
     *
     ********************************************************************/
    protected void createItself() {
	loadIcons();
	getTableHeader().setReorderingAllowed (false);

	// set renderers for buttons column
	TableColumn buttonColumn =
	    getColumnModel().getColumn (COL_BUTTON);
	if (trashIcon != null)
	    buttonColumn.setMaxWidth (trashIcon.getIconWidth() + 15);
	buttonColumn.setCellRenderer (new ButtonRenderer());
	buttonColumn.setCellEditor (new ButtonEditor());
 	buttonColumn.setHeaderRenderer (new TableCellRenderer() {
		public Component getTableCellRendererComponent
		(JTable table, Object value, boolean isSelected,
		 boolean hasFocus, int row, int column) {
		    return (JComponent)value;
		}
	    });
	buttonColumn.setHeaderValue (new JButton ("", trashIcon));
    }

    /*********************************************************************
     * Load shared icons.
     ********************************************************************/
    protected void loadIcons() {
	if (deleteDataIcon == null) deleteDataIcon = loadIcon ("images/smallRemove.gif");
	if (trashIcon == null) trashIcon = loadIcon ("images/smallTrash.gif");
	if (tAreaIcon == null) tAreaIcon = loadIcon ("images/smallMoreLines.gif");
    }

    /*********************************************************************
     * Load shared icon.
     ********************************************************************/
    protected static Icon loadIcon (String path) {
	return SwingUtils.createIcon (path, Dashboard.class);
    }

    /*********************************************************************
     * Implement table header tool tips
     ********************************************************************/
    protected JTableHeader createDefaultTableHeader() {
	return new JTableHeader (columnModel) {
		public String getToolTipText (MouseEvent e) {
		    java.awt.Point p = e.getPoint();
		    int index = columnModel.getColumnIndexAtX (p.x);
		    int realIndex = 
			columnModel.getColumn (index).getModelIndex();
		    return tableModel.columnToolTips [realIndex];
		}
	    };
    }

    /*********************************************************************
     * Put this table in a scrollable pane.
     ********************************************************************/
    public JScrollPane scrollable() {
 	return new JScrollPane (this);
    }

    /**************************************************************************
     *
     **************************************************************************/
    class DeleteRowButton extends JButton {
	int rowToDelete = -1;
	public DeleteRowButton() {
	    super();
	    setText ("");
	    setIcon (deleteDataIcon);
	    setToolTipText ("Remove this data from this service");
 	    setFocusPainted (false);
	    addActionListener (new ActionListener() {
		    public void actionPerformed (ActionEvent e) {
			if (rowToDelete >= 0) {
 			    tableModel.removeRow (rowToDelete);
			}
		    }
		});
	}
	public void setRowToDelete (int row) {
	    rowToDelete = row;
	}
    }

    /**************************************************************************
     *
     **************************************************************************/
    class ButtonRenderer extends DeleteRowButton
	implements TableCellRenderer {
	public ButtonRenderer() {
	    setOpaque (true);
	}	
	public Component getTableCellRendererComponent (JTable table,
							Object value,
							boolean isSelected,
							boolean hasFocus,
							int row, int column) {
	    return this;
	}
    }

    /**************************************************************************
     *
     **************************************************************************/
    class ButtonEditor extends AbstractCellEditor
	implements TableCellEditor {
	public Object getCellEditorValue() {
	    return null;
	}
	public Component getTableCellEditorComponent (JTable table,
						      Object value,
						      boolean isSelected,
						      int row, int column) {
	    DeleteRowButton button = new DeleteRowButton();
	    button.setRowToDelete (row);
	    return button;
	}
    }

    /**************************************************************************
     *
     * Data model of this table.
     *
     **************************************************************************/
    protected abstract class CommonDataTableModel
	extends AbstractTableModel {

	// should be filled by subclasses
	protected String[] columnToolTips;
	protected String[] columnNames = new String[] {};
	protected Class[] columnClasses = new Class[] {};
	protected Vector data = new Vector();

	abstract public void addEmptyData();

	/**************************************************************************
	 * Used to fill the table programatically. It clear the whole
	 * table a put given data there.
	 **************************************************************************/
	public void setData (MobyData[] newData) {
	    synchronized (this) {
		int rowCount = getRowCount();
		for (int i = rowCount-1; i >= 0; i--)
		    removeRow (i);
		for (int i = 0; i < newData.length; i++)
		    data.addElement (newData[i]);
		fireTableDataChanged();
	    }
	}

	public Vector getData() {
	    return data;
	}

	public int getColumnCount() {
	    return columnNames.length;
	}

	public int getRowCount() {
	    return data.size();
	}

	public String getColumnName (int col) {
	    return columnNames [col];
	}

	public Class getColumnClass (int col) {
	    return columnClasses [col];
	}

	public void removeRow (int row) {
	    try {
		data.removeElementAt (row);
		fireTableRowsDeleted (row, row);
	    } catch (Exception e) {
		log.error (e.toString());
	    }
	}
    }


}
