/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package presenter;

import javax.swing.JTable; 
import javax.swing.JTextArea; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableColumn; 
import javax.swing.table.TableColumnModel; 
import java.awt.Component; 
import java.util.Enumeration; 
import java.util.HashMap; 
import java.util.Map; 
 
/** 
 * The standard class for rendering (displaying) individual cells in a JTable. 
 * This class inherits from JTextArea, a standard component class. 
 * However JTextArea is a multi-line area that displays plain text. 
 * 
 * This class implements TableCellRenderer , i.e. interface. 
 * This interface defines the method required by any object that 
 * would like to be a renderer for cells in a JTable. 
 * 
 * @author Manivel 
 * @see JTable 
 * @see JTextArea 
 */ 
 
public class TextAreaRenderer extends JTextArea implements TableCellRenderer { 
    private final DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); 
 
    // Column heights are placed in this Map 
    private final Map<JTable, Map<Object, Map<Object, Integer>>> tablecellSizes = new HashMap<JTable, Map<Object, Map<Object, Integer>>>(); 
 
    /** 
     * Creates a text area renderer. 
     */ 
    public TextAreaRenderer() { 
        setLineWrap(true); 
        setWrapStyleWord(true); 
    } 
 
    /** 
     * Returns the component used for drawing the cell.  This method is 
     * used to configure the renderer appropriately before drawing. 
     * 
     * @param jTable3      - JTable object 
     * @param value      - the value of the cell to be rendered. 
     * @param isSelected - isSelected   true if the cell is to be rendered with the selection highlighted; 
     *                   otherwise false. 
     * @param hasFocus   - if true, render cell appropriately. 
     * @param row        - The row index of the cell being drawn. 
     * @param column     - The column index of the cell being drawn. 
     * @return - Returns the component used for drawing the cell. 
     */ 
    @Override
    public Component getTableCellRendererComponent(JTable jTable3, Object value, boolean isSelected,boolean hasFocus, int row, int column) { 
        // set the Font, Color, etc. 
        renderer.getTableCellRendererComponent(jTable3, value, isSelected, hasFocus, row, column); 
        setForeground(renderer.getForeground()); 
        setBackground(renderer.getBackground()); 
        setBorder(renderer.getBorder()); 
        setFont(renderer.getFont()); 
        setText(renderer.getText()); 
 
        TableColumnModel columnModel = jTable3.getColumnModel(); 
        setSize(columnModel.getColumn(column).getWidth(), 0); 
        int height_wanted = (int) getPreferredSize().getHeight(); 
        addSize(jTable3, row, column, height_wanted); 
        height_wanted = findTotalMaximumRowSize(jTable3, row); 
        
        if (height_wanted != jTable3.getRowHeight(row)) { 
            jTable3.setRowHeight(row, height_wanted); 
        } 
        return this; 
    } 
 
    /** 
     * @param jTable3  - JTable object 
     * @param row    - The row index of the cell being drawn. 
     * @param column - The column index of the cell being drawn. 
     * @param height - Row cell height as int value 
     *               This method will add size to cell based on row and column number 
     */ 
    private void addSize(JTable jTable3, int row, int column, int height) { 
        Map<Object, Map<Object, Integer>> rowsMap = tablecellSizes.get(jTable3); 
        if (rowsMap == null) { 
            tablecellSizes.put(jTable3, rowsMap = new HashMap<Object, Map<Object, Integer>>()); 
        } 
        Map<Object, Integer> rowheightsMap = rowsMap.get(row); 
        if (rowheightsMap == null) { 
            rowsMap.put(row, rowheightsMap = new HashMap<Object, Integer>()); 
        } 
        rowheightsMap.put(column, height); 
    } 
 
    /** 
     * Look through all columns and get the renderer.  If it is 
     * also a TextAreaRenderer, we look at the maximum height in 
     * its hash table for this row. 
     * 
     * @param jTable3 -JTable object 
     * @param row   - The row index of the cell being drawn. 
     * @return row maximum height as integer value 
     */ 
    private int findTotalMaximumRowSize(JTable jTable3, int row) { 
        int maximum_height = 0; 
        Enumeration<TableColumn> columns = jTable3.getColumnModel().getColumns(); 
        while (columns.hasMoreElements()) { 
            TableColumn tc = columns.nextElement(); 
            TableCellRenderer cellRenderer = tc.getCellRenderer(); 
            if (cellRenderer instanceof TextAreaRenderer) { 
                TextAreaRenderer tar = (TextAreaRenderer) cellRenderer; 
                maximum_height = Math.max(maximum_height, 
                tar.findMaximumRowSize(jTable3, row)); 
            } 
        } 
        
        return maximum_height; 
    } 
 
    /** 
     * This will find the maximum row size 
     * 
     * @param jTable3 - JTable object 
     * @param row   - The row index of the cell being drawn. 
     * @return row maximum height as integer value 
     */ 
    private int findMaximumRowSize(JTable jTable3, int row) { 
        Map<Object, Map<Object, Integer>> rows = tablecellSizes.get(jTable3); 
        if (rows == null) return 0; 
        Map<Object, Integer> rowheights = rows.get(row); 
        if (rowheights == null) return 0; 
        int maximum_height = 0; 
        for (Map.Entry<Object, Integer> entry : rowheights.entrySet()) { 
            int cellHeight = entry.getValue(); 
            maximum_height = Math.max(maximum_height, cellHeight); 
        } 
        return maximum_height; 
    } 
}