/*******************************************************************************
 * 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.memo;

/*
 * InvoiceListBox.java
 *
 * Created on April 3, 2006
 */

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

import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.CellEditorListener;
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.Memo;
import lu.tudor.santec.gecamed.billing.gui.HTMLWrappingCellRenderer;
import lu.tudor.santec.gecamed.core.gui.utils.TableSorter;
import lu.tudor.santec.gecamed.usermanagement.ejb.entity.beans.GecamedUser;
import lu.tudor.santec.i18n.Relocalizable;

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

public class MemoListBox extends JScrollPane implements Relocalizable
    {
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private JTable           	m_MemoTable;
    private MemoListModel		m_Memos;
    private TableSorter			m_MemoSorter;
    private MemoRenderer		m_MemoRenderer;
    private MemoEditorField		m_NoteEditor;
     
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************
 
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************

      private static int c_CellMargin = 5;
      
      private static final int c_LockedColumnWidth 		 = 2;
      private static final int c_CreationDateColumnWidth = 15;
      private static final int c_AuthorColumnWidth 		 = 10;
      private static final int c_NoteColumnWidth 		 = 73;
       
      static final public int c_ColumnWidths [] = { c_LockedColumnWidth,
    	  											 c_CreationDateColumnWidth,
    	  											 c_AuthorColumnWidth,
    	  											 c_NoteColumnWidth   };

//***************************************************************************
//* Internal Class Definitions	                                          *
//***************************************************************************

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

public MemoListBox ()
    {	
	super ();
    
    int			l_Count;	
    TableColumn  l_Column;
     
    m_Memos 	 = new MemoListModel ();
    m_MemoSorter = new TableSorter ();
    m_MemoSorter.setTableModel(m_Memos);
    
    m_MemoRenderer = new MemoRenderer ();
    
    m_MemoTable = new JTable (m_MemoSorter);
    //m_MemoTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
    m_MemoTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    
    for (l_Count=0; l_Count < m_Memos.getColumnCount(); l_Count++)
    	{
    	if (m_Memos.getColumnClass(l_Count) != null)	
    	    m_MemoTable.setDefaultRenderer (m_Memos.getColumnClass(l_Count), m_MemoRenderer);
     	}
    
    m_NoteEditor = new MemoEditorField ();
    
    l_Column = m_MemoTable.getColumnModel().getColumn(MemoListModel.c_NoteColumn);
    l_Column.setCellRenderer(new HTMLWrappingCellRenderer());
    l_Column.setCellEditor (m_NoteEditor);

    m_MemoTable.setColumnSelectionAllowed (false);
    m_MemoTable.setShowGrid (false);
 	
    m_MemoSorter.setTableHeader(m_MemoTable.getTableHeader());
    m_MemoSorter.setSortingStatus (MemoListModel.c_CreationTimeColumn, TableSorter.ASCENDING);
       
    this.setViewportView (m_MemoTable);
    }

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

public void setCurrentAuthor (GecamedUser p_Author)
	{	
	m_Memos.setCurrentAuthor(p_Author);
	}

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

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

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

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

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

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

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

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

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

public void addCellEditorListener (CellEditorListener p_Listener)
	{
    m_NoteEditor.addCellEditorListener(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_MemoTable.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_MemoTable.getTableHeader().getDefaultRenderer();
    		}
    
    l_Component = l_Renderer.getTableCellRendererComponent(m_MemoTable,
    													    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_MemoTable.getRowCount(); l_Row++) 
    		{
    		l_Renderer = m_MemoTable.getCellRenderer(l_Row, p_Column);
    		l_Component = l_Renderer.getTableCellRendererComponent(m_MemoTable, 
    															m_MemoTable.getValueAt(l_Row, p_Column), 
    				                                               false, false, l_Row, p_Column);
        
    		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_MemoTable.getRowHeight();

    // Determine highest cell in the row
    for (l_Column = 0; l_Column < m_MemoTable.getColumnCount(); l_Column++) 
    		{
    		l_Renderer = m_MemoTable.getCellRenderer(p_Row, l_Column);
    		l_Component = m_MemoTable.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_MemoTable.getRowHeight() != l_RowHeight)
    		m_MemoTable.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
        
    m_MemoRenderer.relocalize ();
    m_MemoTable.createDefaultColumnsFromModel ();
    }

//---------------------------------------------------------------------------
/**
 * doLayout is the main entry point for JTable resizing and row/column space
 * distribution. The ActListBox class overrides the method to impose its own
 * distribution scheme. Width of columns is expressed as percents and we want
 * the table to reflect this distribution. 
 */
//---------------------------------------------------------------------------

public void doLayout ()
	{
    TableColumn  l_Column;
	double		l_Width;
	int			l_Index;
	int			l_ColumnWidth;
	
	super.doLayout ();
	
	l_Width = (double) m_MemoTable.getWidth () / 100;
	
	for (l_Index = 0; l_Index < c_ColumnWidths.length; l_Index++)
		{
		l_Column = m_MemoTable.getColumnModel().getColumn(l_Index);
		l_ColumnWidth = (int)(l_Width * c_ColumnWidths[l_Index]);
		l_Column.setPreferredWidth(l_ColumnWidth);
		}
	}

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

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

public boolean isEditing ()
	{
    return m_MemoTable.isEditing();
	}

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

public void addMemo (Memo p_Memo)
    {
    if (p_Memo != null)
        {
        m_Memos.addMemo (p_Memo);
        m_MemoTable.repaint();
        }
    }

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

public void removeSelectedMemo ()
    {
    int []      l_SelectedRows;
    
    int         l_Selection;
    int			l_ModelRow;
    
    l_Selection = m_MemoTable.getSelectedRowCount();
    
    if (l_Selection > 0)
        {
        l_SelectedRows    = m_MemoTable.getSelectedRows ();
       
        for (l_Selection = l_SelectedRows.length - 1; l_Selection >= 0; l_Selection--)
            {
        	l_ModelRow = m_MemoSorter.modelIndex(l_SelectedRows [l_Selection]);
        	m_Memos.removeMemoAt (l_ModelRow);
            }
        
        m_MemoTable.clearSelection();
        m_MemoTable.revalidate();
        }
    }

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

public void removeAllMemos ()
    {
	m_Memos.removeAllMemos();
	m_MemoTable.clearSelection();
	m_MemoTable.revalidate();
    }

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

public Memo[] getSelectedMemos ()
    {
	Memo []  l_SelectedMemos = null;    
    int []   l_SelectedRows;   
    int      l_Selection;
    int		 l_ModelRow;
    
    l_Selection = m_MemoTable.getSelectedRowCount();
    
    if (l_Selection > 0)
        {
        l_SelectedRows    = m_MemoTable.getSelectedRows ();
        l_SelectedMemos = new Memo [l_Selection];
        
        for (l_Selection = 0; l_Selection < l_SelectedRows.length; l_Selection++)
            {
        	l_ModelRow = m_MemoSorter.modelIndex(l_SelectedRows [l_Selection]);
         	l_SelectedMemos [l_Selection] = m_Memos.getMemoAt (l_ModelRow);
            }
        }

    return (l_SelectedMemos);
    }

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

public void selectMemoAt (int p_Row)
	{
    ListSelectionModel	l_SelectionModel;
	int		 			l_ViewRow;
	
    l_ViewRow = m_MemoSorter.viewIndex (p_Row);
	if ((l_ViewRow >= 0) && (l_ViewRow < m_Memos.getRowCount()))
		{
		l_SelectionModel = m_MemoTable.getSelectionModel();
		l_SelectionModel.setSelectionInterval(l_ViewRow, l_ViewRow);
		}
	}

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

public int getMemoCount ()
	{
	return m_Memos.getRowCount();
	}

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

public void setMemos (Set <Memo> p_Memos)
    {
    m_Memos.setMemos(p_Memos);
    }    
 
//---------------------------------------------------------------------------

public Set <Memo> getMemos ()
    {
    return m_Memos.getMemos();
    }    
    
//---------------------------------------------------------------------------

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

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

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

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

public void selectLastMemo ()
    {
    ListSelectionModel	l_Selection;	
    JScrollBar			l_ScrollBar;
    int 				l_Row;
    float				l_ScrollValue;
    
    l_Row = m_Memos.getRowCount() - 1;
	l_Row = m_MemoSorter.viewIndex(l_Row);
    
    l_Selection = m_MemoTable.getSelectionModel();
    l_Selection.setSelectionInterval (l_Row,l_Row);
		
    l_ScrollBar = getVerticalScrollBar ();		
    l_ScrollValue = (l_ScrollBar.getMaximum() - l_ScrollBar.getMinimum()); 
		
    l_ScrollBar.setValue ((int)l_ScrollValue);
    }

//---------------------------------------------------------------------------
/**
 * sets input focus on code column of currently selected act.
 */
//---------------------------------------------------------------------------

public void focusOnSelectedMemo ()
	{
	int   l_Selection;
    
    l_Selection = m_MemoTable.getSelectedRowCount();
	if (l_Selection == 1)
		{
		l_Selection = m_MemoTable.getSelectedRow();
		if (m_MemoTable.editCellAt(l_Selection,MemoListModel.c_NoteColumn))
			m_MemoTable.getEditorComponent().requestFocusInWindow();
		}
	}

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

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