/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.billing.gui.ledger;

import java.awt.Component;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.util.Collection;

import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Ledger;
import lu.tudor.santec.gecamed.core.gui.utils.TableSorter;
import lu.tudor.santec.i18n.Relocalizable;

//***************************************************************************
//* Class Definition                                                        *
//***************************************************************************

public class LedgerListBox extends JScrollPane implements Relocalizable
    {
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private JTable       				m_LedgerTable;
    private LedgerListModel				m_Ledgers;
    private TableSorter					m_LedgerSorter;
    private LedgerRenderer				m_LedgerRenderer;
     
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************

    private static int c_CellMargin = 5;
         
//***************************************************************************
//* Internal Class Definitions	                                          	*
//***************************************************************************

//***************************************************************************
//* Constructor(s)                                                          *
//***************************************************************************

public LedgerListBox ()
    {	
	super ();
    
    int			l_Count;	
    
    m_Ledgers = new LedgerListModel ();
    m_LedgerSorter = new TableSorter ();
    m_LedgerSorter.setTableModel(m_Ledgers);
    
    m_LedgerRenderer = new LedgerRenderer ();
    
    m_LedgerTable = new JTable (m_LedgerSorter);
    m_LedgerTable.setSelectionMode (ListSelectionModel.SINGLE_SELECTION);
    m_LedgerTable.setRowSelectionAllowed(false);
    m_LedgerTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
    
    for (l_Count=0; l_Count < m_Ledgers.getColumnCount(); l_Count++)
    	{
    	if (m_Ledgers.getColumnClass (l_Count) != null)	
    		m_LedgerTable.setDefaultRenderer (m_Ledgers.getColumnClass(l_Count), m_LedgerRenderer);
     	}
    
    m_LedgerTable.setColumnSelectionAllowed (false);
    m_LedgerTable.setShowGrid (false);
    m_LedgerTable.setShowVerticalLines(true);
    
    m_LedgerSorter.setTableHeader(m_LedgerTable.getTableHeader());
    m_LedgerSorter.setSortingStatus(LedgerListModel.c_TransactionDateColumn, TableSorter.DESCENDING);
    
    this.setViewportView (m_LedgerTable);
    }

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Primitives		                                                  *
//***************************************************************************
//---------------------------------------------------------------------------

public void addListSelectionListener (ListSelectionListener p_Listener)
    {
    ListSelectionModel	l_Selection;	
    
    l_Selection = m_LedgerTable.getSelectionModel();
    l_Selection.addListSelectionListener (p_Listener);
    }

//---------------------------------------------------------------------------

public void addMouseListener (MouseListener p_Listener)
    {
    m_LedgerTable.addMouseListener (p_Listener);
    }    

//---------------------------------------------------------------------------

public void addKeyListener (KeyListener p_Listener)
    {
    m_LedgerTable.addKeyListener (p_Listener);
    }    

//---------------------------------------------------------------------------

public void addTableModelListener (TableModelListener p_Listener)
    {
	m_Ledgers.addTableModelListener(p_Listener);
    }

//---------------------------------------------------------------------------
//Sets the preferred width of the visible column specified by vColIndex. The column
// will be just wide enough to show the column head and the widest cell in the column.
// margin pixels are added to the left and right
// (resulting in an additional width of 2*margin pixels).
//---------------------------------------------------------------------------

public void packColumn (int p_Column, int p_Margin) 
	{
	DefaultTableColumnModel	l_ColumnModel;
	TableColumn 				l_Column;
	TableCellRenderer		l_Renderer;
	Component				l_Component;
	
	int		   				l_Width;
    int						l_Row;
	
	l_ColumnModel = (DefaultTableColumnModel)m_LedgerTable.getColumnModel();
	l_Column = l_ColumnModel.getColumn(p_Column);
	l_Width = 0;

    // First step consists in getting width of column header

    l_Renderer = l_Column.getHeaderRenderer();
    if (l_Renderer == null) 
    		{
    		l_Renderer = m_LedgerTable.getTableHeader().getDefaultRenderer();
    		}
    
    l_Component = l_Renderer.getTableCellRendererComponent(m_LedgerTable,
    													    l_Column.getHeaderValue(), 
    													    false, false, 0, 0);
    l_Width = l_Component.getPreferredSize().width;

    // Next we're going to iterate through all the rows of this columns, in order to
    // to find the widest one

    for (l_Row=0; l_Row < m_LedgerTable.getRowCount(); l_Row++) 
    		{
    		l_Renderer = m_LedgerTable.getCellRenderer(l_Row, p_Column);
         
      		try {
    			l_Component = l_Renderer.getTableCellRendererComponent(m_LedgerTable, 
    																   m_LedgerTable.getValueAt(l_Row, p_Column), 
    				                                               	   false, false, l_Row, p_Column);
    			}
    		catch (Exception p_Exception)
    			{
    			// TODO Nasty Workaround
    			// Renderer sometimes throws unexplicable NullPointerExceptions.
    			// Not catching them results in Table not being properly packed.
    			}

    		l_Width = Math.max (l_Width, l_Component.getPreferredSize().width);
    		}

    // Add margin
    l_Width += 2*p_Margin;

    // Set the width
    l_Column.setPreferredWidth(l_Width);
	}

//---------------------------------------------------------------------------
//Returns the preferred height of a row.
// The result is equal to the tallest cell in the row.
//---------------------------------------------------------------------------

public void packRow (int p_Row, int p_Margin) 
	{
    int					l_RowHeight;
    int					l_ComponentHeight;
	int					l_Column;
    TableCellRenderer		l_Renderer;
    Component			l_Component;
    
    // Get the current default height for all rows
    l_RowHeight = m_LedgerTable.getRowHeight();

    // Determine highest cell in the row
    for (l_Column = 0; l_Column < m_LedgerTable.getColumnCount(); l_Column++) 
    		{
    		l_Renderer = m_LedgerTable.getCellRenderer(p_Row, l_Column);
    		l_Component = m_LedgerTable.prepareRenderer(l_Renderer, p_Row, l_Column);
    		l_ComponentHeight = l_Component.getPreferredSize().height + 2*p_Margin;
    		l_RowHeight = Math.max (l_RowHeight, l_ComponentHeight);
    		}
    
    if (m_LedgerTable.getRowHeight() != l_RowHeight)
    		m_LedgerTable.setRowHeight (p_Row,l_RowHeight);
	}

//---------------------------------------------------------------------------
/**
 * Method is part of the Relocalizable interface. The method does everything
 * required to reflect changes of active Locale
 */
//---------------------------------------------------------------------------

public void relocalize ()
    {
    // Make sure JTable re-creates columns using re-localized headers
        
	if (m_LedgerRenderer != null) m_LedgerRenderer.relocalize ();
    	
    if (m_LedgerTable != null) m_LedgerTable.createDefaultColumnsFromModel ();
    }


//***************************************************************************
//* Class Body		                                                    *
//***************************************************************************
//---------------------------------------------------------------------------

public void removeAllLedgers ()
    {
	m_Ledgers.removeAllLedgers();
    m_LedgerTable.clearSelection();
    m_LedgerTable.revalidate();
    }

//---------------------------------------------------------------------------

public void setLedgers (Collection <Ledger> p_Ledgers)
    {
    m_Ledgers.setLedgers(p_Ledgers);
    }    
 
//---------------------------------------------------------------------------

public Collection <Ledger> getLedgers ()
    {
    return m_Ledgers.getLedgers();
    }    
    
//---------------------------------------------------------------------------

public void packColumns ()
	{
	int l_Column;
	
	for (l_Column=0; l_Column < m_LedgerTable.getColumnCount(); l_Column++)
		{
		packColumn (l_Column,c_CellMargin);
		}
	}

//---------------------------------------------------------------------------

public void packRows ()
	{
	int l_Row;
	
	for (l_Row=0; l_Row < m_LedgerTable.getRowCount(); l_Row++)
		{
		packRow (l_Row,c_CellMargin);
		}
	}

//***************************************************************************
//* End of Class															*
//***************************************************************************
}
