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

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

 import java.awt.Component;
import java.awt.Container;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Set;
import java.util.Vector;

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.ChangeEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Act;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Invoice;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Suffix;
import lu.tudor.santec.gecamed.billing.gui.BillingModule;
import lu.tudor.santec.gecamed.billing.gui.HospClassCellEditor;
import lu.tudor.santec.gecamed.billing.gui.PhysicianCellEditor;
import lu.tudor.santec.gecamed.billing.gui.SpinnerEditorField;
import lu.tudor.santec.gecamed.billing.gui.TextWrappingCellRenderer;
import lu.tudor.santec.gecamed.billing.gui.TimeCellEditor;
import lu.tudor.santec.gecamed.billing.gui.act.addinfo.AdditionalInfoEditorField;
import lu.tudor.santec.gecamed.billing.gui.medpres.MedPresCellEditor;
import lu.tudor.santec.gecamed.billing.gui.suffix.SuffixEditorField;
import lu.tudor.santec.gecamed.billing.utils.BillingAdminSettings;
import lu.tudor.santec.gecamed.core.gui.utils.JDateChooserCellEditorGECAMed;
import lu.tudor.santec.gecamed.core.gui.utils.TableSorter;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.HospitalisationClass;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.HospitalisationClassBean;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.HospitalisationClassInterface;
import lu.tudor.santec.i18n.Relocalizable;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.toedter.calendar.JDateChooserCellEditor;

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

public class ActListBox extends JScrollPane implements CellEditorListener,
													   Relocalizable,
													   HospitalisationClassListener
    {
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private static final Vector<String> c_HospitalisationClasses = getHospitalisationClasses();
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(ActListBox.class.getName());
	
	private JTable       				m_ActTable;
    private ActListModel				m_Acts;
    private TableSorter					m_ActSorter;
    private ActRenderer					m_ActRenderer;
    private HospClassCellEditor 		m_HospClassEditor;
    private CodeCellEditor				m_CodeEditor;
    private LabelCellEditor				m_LabelEditor;
    private JDateChooserCellEditor		m_PerformedDateEditor;
    private TimeCellEditor				m_PerformedTimeEditor;
    private PhysicianCellEditor			m_PhysicianEditor;
    private SuffixEditorField			m_SuffixEditor;
    private SpinnerEditorField			m_QuantityEditor;
    private AmountEditor 				m_AmountEditor;
    private AdjustmentEditor 			m_AdjustmentEditor;
    private AdditionalInfoEditorField 	m_InfoEditor;
    private MedPresCellEditor 			m_MedPresEditor;
    private boolean						m_ShowPhysicianColumn;

	private boolean m_ShowMedPrescColumn = true;
	private boolean m_ShowInfoColumn = true;

	private Boolean m_ShowUsernameColumn;

	private Boolean m_ShowAdjustColumn;
	private FocusListener m_MarkOnFocusListener;
	
	private int		m_LastCol = ActListModel.c_CodeColumn;

    
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************

    private static int c_CellMargin = 5;
     
//***************************************************************************
//* Constructor(s)                                                          *
//***************************************************************************

public ActListBox (Collection <Suffix> p_Suffixes, Collection <Physician> p_Physicians)
    {	
	super ();
    
    int			 l_Count;	
    TableColumn  l_Column;
    
    m_ShowPhysicianColumn = ! 	(Boolean) BillingModule.getSetting (BillingAdminSettings.c_SplitBillingSetting);
    m_ShowInfoColumn =  		(Boolean) BillingModule.getSetting (BillingAdminSettings.c_ShowInfoColumnSetting);
    m_ShowMedPrescColumn =  	(Boolean) BillingModule.getSetting (BillingAdminSettings.c_ShowMedPrescColumnSetting);
    m_ShowUsernameColumn =  	(Boolean) BillingModule.getSetting (BillingAdminSettings.c_ShowUsernameColumnSetting);
    m_ShowAdjustColumn =  		(Boolean) BillingModule.getSetting (BillingAdminSettings.c_ShowAdjustColumnSetting);

    m_Acts = new ActListModel (m_ShowPhysicianColumn, m_ShowInfoColumn, m_ShowMedPrescColumn, m_ShowUsernameColumn, m_ShowAdjustColumn);
    m_ActSorter = new TableSorter ();
    m_ActSorter.setTableModel(m_Acts);
    
    m_ActRenderer = new ActRenderer (p_Physicians);
    
    m_ActTable = new JTable (m_ActSorter);
    m_ActTable.setSelectionMode (ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    m_ActTable.setAutoCreateRowSorter(false);
    
    for (l_Count=0; l_Count < m_Acts.getColumnCount(); l_Count++)
    	{
	    if (m_Acts.getColumnClass (l_Count) != null)	
	    	m_ActTable.setDefaultRenderer (m_Acts.getColumnClass(l_Count), m_ActRenderer);
     	}
    
//    m_ActTable.setSurrendersFocusOnKeystroke(true);
    m_ActTable.setColumnSelectionAllowed (false);
    m_ActTable.setShowGrid (false);
    
    m_ActTable.addMouseListener(new MouseAdapter() {
    	public void mouseClicked(MouseEvent e) {
//    		System.out.println(e);
    		m_LastCol = m_ActTable.columnAtPoint(e.getPoint());
//    		System.out.println("Col: "+ m_LastCol);
    	};
	});
    
    m_CodeEditor          	= new CodeCellEditor ();
    m_CodeEditor.addCellEditorListener(this);
    
    m_LabelEditor		  	= new LabelCellEditor ();
    m_PerformedDateEditor 	= new JDateChooserCellEditorGECAMed();
    m_PerformedTimeEditor 	= new TimeCellEditor ();
    m_SuffixEditor 			= new SuffixEditorField (p_Suffixes);
    m_QuantityEditor 		= new SpinnerEditorField (0, -1000, 1000, 1);
    m_HospClassEditor 		= new HospClassCellEditor(c_HospitalisationClasses);
    m_AmountEditor 			= new AmountEditor();
    m_AdjustmentEditor 		= new AdjustmentEditor();
    
    
    addMarkAllFocusListner(m_CodeEditor.getTextField());
//    addMarkAllFocusListner(m_QuantityEditor.getSpinner()); // not working, although FocusListener is added and called
    addMarkAllFocusListner(m_AmountEditor.getTextField());
    addMarkAllFocusListner(m_AdjustmentEditor.getTextField());
    
    l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_HospClassColumn));
    l_Column.setCellEditor (m_HospClassEditor);
    
    l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_DateColumn));
    l_Column.setCellEditor (m_PerformedDateEditor);
    
    l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_TimeColumn));
    l_Column.setCellEditor (m_PerformedTimeEditor);

    if (m_ShowPhysicianColumn)
    	{
    	m_PhysicianEditor = new PhysicianCellEditor (p_Physicians);
    	l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_PhysicianColumn));
    	l_Column.setCellEditor (m_PhysicianEditor);
    	}
    
    l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_CodeColumn));
    l_Column.setCellEditor (m_CodeEditor);
    
    l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_SuffixColumn));
    l_Column.setCellEditor (m_SuffixEditor);
    
    if (m_ShowInfoColumn)
	{
    	m_InfoEditor = new AdditionalInfoEditorField (m_Acts);
    	l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_AdditionalInfoColumn));
    	l_Column.setCellEditor (m_InfoEditor);
	}
    
    l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_LabelColumn));
    l_Column.setCellEditor (m_LabelEditor);   
    l_Column.setCellRenderer(new TextWrappingCellRenderer());
    
    l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_QuantityColumn));
    l_Column.setCellEditor (m_QuantityEditor);
    
    l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_AdjustmentColumn));
    l_Column.setCellEditor (m_AdjustmentEditor);
    
    l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_AmountColumn));
    l_Column.setCellEditor (m_AmountEditor);
    
    if (m_ShowMedPrescColumn)
	{
    	m_MedPresEditor		  	= new MedPresCellEditor ();
    	l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_MedPrescCodeColumn));
    	l_Column.setCellEditor (m_MedPresEditor);
    	l_Column.setCellRenderer(m_MedPresEditor);
	}
    
    if (m_ShowUsernameColumn)
	{
    	UsernameRenderer m_UsernameRenderer = new UsernameRenderer();
		l_Column = m_ActTable.getColumnModel().getColumn(m_Acts.getModelToViewColumn(ActListModel.c_UsernameColumn));
		l_Column.setCellRenderer(m_UsernameRenderer);
	}
	
    m_ActSorter.setTableHeader(m_ActTable.getTableHeader());
    
    this.setViewportView (m_ActTable);
    
    BillingModule.getInstance().addHospitalisationClassListener(this);
    }

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

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

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

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

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

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

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

public void removeTableModelListener (TableModelListener p_Listener)
    {
	m_Acts.removeTableModelListener(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_ActTable.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_ActTable.getTableHeader().getDefaultRenderer();
    		}
    
    l_Component = l_Renderer.getTableCellRendererComponent(m_ActTable,
    													    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_ActTable.getRowCount(); l_Row++) 
    		{
    		l_Renderer = m_ActTable.getCellRenderer(l_Row, p_Column);
         
      		try {
    			l_Component = l_Renderer.getTableCellRendererComponent(m_ActTable, 
    																   m_ActTable.getValueAt(l_Row, p_Column), 
    				                                               	   false, false, l_Row, p_Column);
    			l_Width = Math.max (l_Width, l_Component.getPreferredSize().width);
    			}
    		catch (Exception p_Exception)
    			{
    			// TODO Nasty Workaround
    			// Renderer sometimes throws unexplicable NullPointerExceptions.
    			// Not catching them results in Table not being properly packed.
    			}

    		}

    // 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_ActTable.getRowHeight();

    // Determine highest cell in the row
    for (l_Column = 0; l_Column < m_ActTable.getColumnCount(); l_Column++) 
    		{
    		l_Renderer = m_ActTable.getCellRenderer(p_Row, l_Column);
    		l_Component = m_ActTable.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_ActTable.getRowHeight() != l_RowHeight)
    		m_ActTable.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_ActRenderer != null) m_ActRenderer.relocalize ();
    	
    if (m_ActTable != null) m_ActTable.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 ()
	{
    TableColumnModel	l_ColumnModel;
	TableColumn  		l_Column;
	double				l_Width;
	int					l_ColumnWidth;
	int					l_Index;
	
	super.doLayout ();
	
	l_Width = (double) m_ActTable.getWidth () / 100;
	
	l_ColumnModel = m_ActTable.getColumnModel ();
	
	for (l_Index = 0; l_Index < m_Acts.getColumnCount(); l_Index ++)
		{
		l_Column = l_ColumnModel.getColumn (l_Index);
		if (l_Column != null)
			{
			l_ColumnWidth = (int)(l_Width * m_Acts.getColumnWidth(l_Index));
			l_Column.setPreferredWidth(l_ColumnWidth);
			}
		}
	}

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

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

public int addAct (Act p_Act)
    {
	int	l_SelectedRow;
	Act l_SelectedAct;
	int	l_Row = -1;
	
	
    if (p_Act != null)
        {
    	l_SelectedRow = m_ActSorter.modelIndex(m_ActTable.getSelectedRow());
    	l_SelectedAct = m_Acts.getActAt(l_SelectedRow);
    	
    	if (l_SelectedAct == null) {
    		// get the last row in the table
    		try {
    			l_SelectedRow = m_ActSorter.modelIndex(m_Acts.getRowCount()-1);
    			l_SelectedAct = m_Acts.getActAt (l_SelectedRow);				
			} catch (Exception e) {
				logger.warn("Error while retrieving last act of invoice", e);
			}
    	}
    	
    	// copy hosp class from selected Act
    	if (l_SelectedAct != null)
    	{
    		if (p_Act.getHospitalisationClass() == null && l_SelectedAct.getHospitalisationClass() != null) {
    			p_Act.setHospitalisationClass(l_SelectedAct.getHospitalisationClass(), BillingModule.getInstance().getCurrentInvoice());
    		}
    
	    	// copy physician from selected Act
	    	if (p_Act.getPhysicianId() == null && l_SelectedAct.getPhysicianId() != null) {
	    		p_Act.setPhysicianId (l_SelectedAct.getPhysicianId());
	    	}
	    	
	    	// copy MED.PRES from selected Act
	    	if (p_Act.getMedPrescCode() == null && l_SelectedAct.getMedPrescCode() != null) {
	    		p_Act.setMedPrescCode(l_SelectedAct.getMedPrescCode());    		    		
	    	}    
	    	
	    	// copy time from selected Act
	    	if (p_Act.getShowTime() == null && l_SelectedAct.getShowTime() != null) {
	    		p_Act.setShowTime(l_SelectedAct.getShowTime());    
	    	}

	    	if (p_Act.getPerformedDate() == null && l_SelectedAct.getPerformedDate() != null) {
	    		p_Act.setPerformedDate(l_SelectedAct.getPerformedDate());        		
	    	}
    	}
    	
    	if (l_SelectedAct == null)
    		l_Row = m_Acts.addAct (p_Act);
    	else 
    		l_Row = m_Acts.addAct(p_Act, l_SelectedRow + 1);
        m_ActTable.revalidate();
        }
    
    return l_Row;
    }

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

public void updateResults (Vector <Act> p_Acts)
    {
    Act  l_Act;
    int  l_ActCount;
    
    if (p_Acts == null) return;
        
    for (l_ActCount = 0; l_ActCount < p_Acts.size(); l_ActCount++)
        {
        l_Act = p_Acts.elementAt(l_ActCount);
            
        if (!containsAct (l_Act.getCode())) addAct (l_Act);
        }
    }

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

public void removeSelectedActs ()
    {
    int []      l_SelectedRows;
    int         l_Selection;
    int			l_ModelRow;
    
    l_Selection = m_ActTable.getSelectedRowCount();
    
    if (l_Selection > 0)
        {
        l_SelectedRows    = m_ActTable.getSelectedRows ();
       
        for (l_Selection = l_SelectedRows.length - 1; l_Selection >= 0; l_Selection--)
            {
        	l_ModelRow = m_ActSorter.modelIndex(l_SelectedRows [l_Selection]);
            m_Acts.removeActAt (l_ModelRow);
            }
        
        m_ActTable.clearSelection();
        m_ActTable.revalidate();
        }
    }

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

public void removeAllActs ()
    {
	m_Acts.removeAllActs();
    m_ActTable.clearSelection();
    m_ActTable.revalidate();
    }

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

public Act[] getSelectedActs ()
    {
	Act []  l_SelectedActs = null;    
    int []      l_SelectedRows;   
    int         l_Selection;
    int			l_ModelRow;
    
    l_Selection = m_ActTable.getSelectedRowCount();
    
    if (l_Selection > 0)
        {
        l_SelectedRows    = m_ActTable.getSelectedRows ();
        l_SelectedActs = new Act [l_Selection];
        
        for (l_Selection = 0; l_Selection < l_SelectedRows.length; l_Selection++)
            {
        	l_ModelRow = m_ActSorter.modelIndex(l_SelectedRows [l_Selection]);
            l_SelectedActs [l_Selection] = m_Acts.getActAt (l_ModelRow);
            }
        }

    return (l_SelectedActs);
    }

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

public Act getSelectedAct ()
	{
	Act []  l_SelectedActs;
	
	l_SelectedActs = this.getSelectedActs();
	
		if (l_SelectedActs != null && l_SelectedActs.length > 0) {
			return l_SelectedActs [0];		
		} else {
			return null;
		}
	}

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

public boolean selectAct (String p_Code)
    {
    int 				l_Row;
    
    l_Row = m_Acts.findAct (p_Code);
	
    return select(l_Row);
    }


public boolean select (int p_Row)
	{
	ListSelectionModel	l_Selection;	
	JScrollBar			l_ScrollBar;
	float				l_ScrollValue;
	boolean 			l_Selected = false;
	
	
    if (p_Row >= 0)
        {
    	p_Row = m_ActSorter.viewIndex(p_Row);
    	
    	l_Selection = m_ActTable.getSelectionModel();
    	l_Selection.setSelectionInterval (p_Row,p_Row);
		
    	l_ScrollBar = getVerticalScrollBar ();
		
    	l_ScrollValue  = (float) p_Row / (float) m_Acts.getRowCount();
    	l_ScrollValue *= (l_ScrollBar.getMaximum() - l_ScrollBar.getMinimum()); 
		
    	l_ScrollBar.setValue ((int)l_ScrollValue);
		
    	l_Selected = true;
        }
   
    return (l_Selected);
    }


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

public void deselectAll ()
	{
	ListSelectionModel	l_Selection;
	
	l_Selection = m_ActTable.getSelectionModel();
	l_Selection.clearSelection();
	}

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

//public void focusOnSelectedCode ()
//	{
//	int   l_Selection;
//    
//    l_Selection = m_ActTable.getSelectedRowCount();
//	if (l_Selection == 1)
//		{
//		l_Selection = m_ActTable.getSelectedRow();
//		if (m_ActTable.editCellAt(l_Selection,m_Acts.getModelToViewColumn(ActListModel.c_CodeColumn)))
//			m_ActTable.getEditorComponent().requestFocusInWindow();
//		}
//	}

public void focusOnSelectedAct ()
{
	int		l_Selection;
	boolean	l_IsEditing;
	
	l_Selection = m_ActTable.getSelectedRowCount();
	if (l_Selection == 1) {
		
		l_Selection = m_ActTable.getSelectedRow();
		l_IsEditing = m_ActTable.editCellAt(l_Selection,m_Acts.getModelToViewColumn(ActListModel.c_CodeColumn));
		
//		if (!l_IsEditing)
//			l_IsEditing = m_ActTable.editCellAt(l_Selection,m_Acts.getModelToViewColumn(ActListModel.c_CodeColumn));
		
		if (l_IsEditing)
			m_ActTable.getEditorComponent().requestFocusInWindow();
	}
}

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

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

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

public void stopEditing ()
	{
	TableCellEditor	l_Editor;
	
	if (m_ActTable.getCellEditor() != null)
		{
		l_Editor = (TableCellEditor) m_ActTable.getCellEditor();
		l_Editor.stopCellEditing();
		}
	}

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

public void setEditable (boolean p_Editable)
	{
	m_Acts.setEditable(p_Editable);
	}

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

public boolean isEditable ()
	{
	return m_Acts.isEditable ();
	}

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

public boolean containsAct (String p_Code)
    {
    if (m_Acts.findAct (p_Code) >= 0) return true;
                                 else return false;
    }    
  
//---------------------------------------------------------------------------

public void setMajoration (double p_Majoration)
	{
	m_Acts.setMajoration(p_Majoration);
	}

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

public void setActs (Set <Act> p_Acts)
    {
	m_Acts.setActs(p_Acts);
    }    
 
//---------------------------------------------------------------------------

public Set <Act> getActs ()
    {
    return m_Acts.getActs();
    }

public Act getActAtViewRow (int row)
{
	return m_Acts.getActAt(m_ActSorter.modelIndex(row));
}
    
//---------------------------------------------------------------------------

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

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

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

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

public void editingCanceled (ChangeEvent p_Event) 
	{
	Act l_Act;
	
	if (p_Event.getSource().equals(m_CodeEditor))
		{
		l_Act = this.getSelectedAct();
		if ((l_Act.getCode() == null) || (l_Act.getCode().length() == 0))
			this.removeSelectedActs();
		}
	}

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

public void editingStopped (ChangeEvent p_Event) 
	{
	}

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

public void setDefaultSorting ()
	{
	if (m_ActTable.getColumnCount() == ActListModel.c_MaxColumns)
		 m_ActSorter.setSortingStatus(ActListModel.c_CodeColumn, TableSorter.ASCENDING);
	else m_ActSorter.setSortingStatus(ActListModel.c_CodeColumn-1, TableSorter.ASCENDING);
	m_ActSorter.setSortingStatus(ActListModel.c_TimeColumn, TableSorter.ASCENDING);
	m_ActSorter.setSortingStatus(ActListModel.c_DateColumn, TableSorter.ASCENDING);
	}

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

private static Vector<String> getHospitalisationClasses ()
	{
	HospitalisationClassInterface 		manager;
	Collection<HospitalisationClass> 	classes;
	Vector<String> 					classAcronyms;
	
	try
		{
		manager 		= (HospitalisationClassInterface) ManagerFactory.getRemote(HospitalisationClassBean.class);
		classes 		= manager.getAllHospitalisationClasses();
		classAcronyms 	= new Vector<String>(classes.size());
		
		for (HospitalisationClass clazz : classes)
			{
			classAcronyms.add(clazz.getAcronym());
			}
		
		return classAcronyms;
		} 
	catch (Exception e)
		{
		logger.log(Level.ERROR, e.getMessage(), e);
		
		classAcronyms = new Vector<String>();
		classAcronyms.add(HospitalisationClass.c_Ambulant);
		classAcronyms.add(HospitalisationClass.c_FirstClass);
		classAcronyms.add(HospitalisationClass.c_SecondClass);
		
		return classAcronyms;
		}
	}

public void hospitalisationClassChanged(Invoice p_Invoice)
	{
	if (p_Invoice != null
			&& p_Invoice.getHospitalisationClass() != null
			&& p_Invoice.getHospitalisationClass().getAcronym() != null)
		{
		String l_Acronym = p_Invoice.getHospitalisationClass().getAcronym();
		
		m_Acts.setInvoice(p_Invoice);
		
		for (Act l_Act : m_Acts.getActs())
			{
			l_Act.setHospitalisationClass(l_Acronym, p_Invoice);
			}
		
		m_ActTable.repaint();
		}
		
	}


	private void findAndMarkTextComponent (Component c)
	{
		if (c instanceof JTextComponent)
		{
			JTextComponent t = (JTextComponent) c;
			Caret caret = t.getCaret();
			caret.setDot(0);
			caret.moveDot(t.getText().length());
		}
	}
	
	
	private void addMarkAllFocusListner (Component c)
	{
		if (m_MarkOnFocusListener == null)
		{
			m_MarkOnFocusListener = new FocusListener()
		    {
		    	public void focusLost (FocusEvent e) {}
		    	
		    	public void focusGained (FocusEvent e)
		    	{
		    		if (e.getSource() instanceof JTextComponent)
		    		{
		    			JTextComponent t = (JTextComponent) e.getSource();
		    			Caret caret = t.getCaret();
		    			caret.setDot(0);
		    			caret.moveDot(t.getText().length());
		    		}
		    	}
		    };
		}
		
		JTextComponent tc = findTextComponent(c);
		if (tc != null)
			tc.addFocusListener(m_MarkOnFocusListener);
		else
			logger.warn("No text component found for component with class " + c.getClass().getName());
	}
	
	
	private JTextComponent findTextComponent (Component component)
	{
		if (component == null)
			return null;
		
		if (component instanceof JTextComponent)
			return (JTextComponent) component;
		
		if (component instanceof Container)
		{
			for (Component childComponent : ((Container)component).getComponents())
			{
				childComponent = findTextComponent(childComponent);
				if (childComponent != null)
					return (JTextComponent) childComponent;
			}
		}
		
		return null;
	}


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