package usda.weru.soil;

// import the necessary java classes, including the Table package
import java.awt.*;
import java.util.*;
import javax.swing.*;

//import java.awt.event.ActionListener;
import java.awt.event.*;
import com.klg.jclass.table.data.JCEditableVectorDataSource;
import com.klg.jclass.table.JCTableEnum;
import com.klg.jclass.table.CellStyleModel;
import com.klg.jclass.table.JCCellRange;
//import com.klg.jclass.table.JCScrollListener;
//import com.klg.jclass.table.JCScrollEvent;
import com.klg.jclass.table.JCEditCellListener;
import com.klg.jclass.table.JCEditCellEvent;
import com.klg.jclass.table.JCCellStyle;
import com.klg.jclass.field.cell.JCTextFieldCellEditor;
import com.klg.jclass.table.JCSelectListener;
import com.klg.jclass.table.JCSelectEvent;

import de.schlichtherle.truezip.file.TFile;
import java.util.List;
import usda.weru.util.Caster;
import usda.weru.util.Util;

/**
 * Simple LiveTable example. Creates a simple table using a JCVectorDataSource.
 */
//public class Grid extends JPanel implements JCEditCellListener, ActionListener {
public class Grid extends usda.weru.util.SimpleTable implements JCEditCellListener, JCSelectListener, ActionListener {

    private static final long serialVersionUID = 1L;

// initialize the Table object
//protected JCTable table;
    private IFC inputRecord;
    private int inputType;
    private final JCEditableVectorDataSource dataSource;
    private final int hdrRows;
    private int bodRows;

// Build the table, point to the data source and define the table
// properties.
    /**
     *
     * @param inprec
     * @param gridType
     */
    public Grid(IFC inprec, int gridType) {
        boolean multiRowFlg = false;

        inputRecord = inprec;
        inputType = gridType;

        setLayout(new java.awt.GridLayout());

        String fileName = "";
        switch (gridType) {
            case 1:
                jctable = new usda.weru.util.ToolTipsTable("IDPanel", new TFile("cfg", "soiltooltips.cfg"));
                ToolTipManager.sharedInstance().registerComponent(jctable);
                jctable.setLabels(new String[]{"", "state", "county", "area", "ssid", "mapunit",
                    "compname", "comppercent", "soilorder", "localphase", "texture", "losstol"});
                fileName = "soil1.cfg";
                multiRowFlg = false;
                break;
            case 2:
                jctable = new usda.weru.util.ToolTipsTable("SurfPanel", new TFile("cfg", "soiltooltips.cfg"));
                ToolTipManager.sharedInstance().registerComponent(jctable);
                jctable.setLabels(new String[]{"", "crustthick", "crustdensity", "cruststability", "crustfract",
                    "loosemass", "loosefract", "randruff", "ridgeorient", "ridgeheight", "ridgespace", "ridgewidth",
                    "albedo", "slope", "surffrag", "bedrockdepth", "resdepth"});
                fileName = "soil2.cfg";
                multiRowFlg = false;
                break;
            case 3:
                jctable = new usda.weru.util.ToolTipsTable("LayerPanel", new TFile("cfg", "soiltooltips.cfg"));
                ToolTipManager.sharedInstance().registerComponent(jctable);
                jctable.setLabels(new String[]{"layernumber", "layerthick", "om", "sand",
                    "silt", "clay", "rock", "vcsand", "csand", "msand", "fsand", "vfsand", "wetbd",
                    "drybd", "aggmd", "aggsd", "agmax", "agmin", "agden", "agstab", "waterinit",
                    "watersat", "waterfc", "waterpwp", "cb", "aep", "satk", "ph", "caco3", "cec", "lep"});
                fileName = "soil3.cfg";
                multiRowFlg = true;
                break;
        }

        Hashtable<String, String> HT_config = readConfig("cfg", fileName);

        readReports(null, repVec, HT_config);
        // Create a vector data source to contain our data
        dataSource = new JCEditableVectorDataSource();

        // Set the cell data in the data source.
        String[][] gridData = inputRecord.getGridValues(inputType);
        String[][] colHeaders = parseHeaders(HT_config, Util.USUnits);
        hdrRows = colHeaders.length;
        bodRows = gridData.length;
        int bodCols = gridData[0].length;

        // Turn off column labels
        jctable.setColumnLabelDisplay(false);

        // Turn on/off row labels
        if (multiRowFlg) {
            jctable.setRowLabelDisplay(true);
        } else {
            jctable.setRowLabelDisplay(false);
        }

        // Set the number of rows in the data source.
        dataSource.setNumRows(bodRows + hdrRows);

        // Set the number of columns in the data source.
        dataSource.setNumColumns(bodCols); // error to fix

        dataSource.setColumnLabels(colHeaders[0]);

        if (multiRowFlg) {
            setRowLabels(hdrRows, bodRows);
        }

        tableData = new String[bodRows + hdrRows + 1][];

        try {
            System.arraycopy(colHeaders, 0, tableData, 0, colHeaders.length);
        } catch (java.lang.ArrayIndexOutOfBoundsException e) {
        }
        System.arraycopy(gridData, 0, tableData, hdrRows, gridData.length);

        // temp fix to get last row to display
        tableData[tableData.length - 1] = new String[gridData[0].length];
        for (int idx = 0; idx < tableData[tableData.length - 1].length; idx++) {
            tableData[tableData.length - 1][idx] = " ";
        }

        makeSpan(colHeaders, bodCols);
        dataSource.setCells(tableData);

        CellStyleModel labelStyle = jctable.getDefaultLabelStyle();

        labelStyle.setBackground(new Color(255, 255, 160));
        labelStyle.setForeground(Color.black);
        labelStyle.setHorizontalAlignment(JCTableEnum.LEFT);
        labelStyle.setClipHints(JCTableEnum.SHOW_NONE);
        labelStyle.setCellBorderSides(JCTableEnum.BORDERSIDE_ALL);
        labelStyle.setEditable(false);
        labelStyle.setTraversable(false);

        jctable.setCellStyle(new JCCellRange(0, 0, 0, bodCols - 1), labelStyle);

        JCCellStyle cs = new JCCellStyle();
        cs.setBackground(new Color(255, 255, 210));
        cs.setForeground(Color.black);
        cs.setHorizontalAlignment(JCTableEnum.CENTER);
        cs.setClipHints(JCTableEnum.SHOW_NONE);
        cs.setCellBorderSides(JCTableEnum.BORDERSIDE_ALL);
        cs.setEditable(false);
        cs.setTraversable(false);

        jctable.setCellStyle(new JCCellRange(1, 0, hdrRows - 1, bodCols - 1), cs);

        jctable.setFrozenRows(hdrRows);
        jctable.setPixelWidth(JCTableEnum.ALLCELLS, JCTableEnum.VARIABLE);
        jctable.setPixelWidth(JCTableEnum.LABEL, 30);
        jctable.setSelectionPolicy(JCTableEnum.SELECT_RANGE);
        jctable.setAutoScroll(JCTableEnum.AUTO_SCROLL_BOTH);
        jctable.setHorizSBDisplay(JCTableEnum.SCROLLBAR_ALWAYS);
        jctable.setHorizSBPosition(JCTableEnum.ATTACH_SIDE);

        int[] cW2 = getColumnWidths(bodCols, HT_config);

        for (int cdx = 0; cdx < cW2.length; cdx++) {
            jctable.setPixelWidth(cdx, cW2[cdx]);
        }

        jctable.addEditCellListener(this);
        jctable.addSelectListener(this);
        jctable.setDataSource(dataSource);

        this.add(jctable);
    }

    /**
     * *********************************************************************
     * wjr
     */
    private void addToolTips(int hdrRows, int bodRows, int bodCols) {
////System.out.println("aTT : " + hdrRows + " " + bodRows + " " + bodCols);
        ErrorRange[] eR = inputRecord.getToolTipText(inputType);
        for (int rdx = hdrRows; rdx < (hdrRows + bodRows); rdx++) {
            for (int cdx = 0; cdx < bodCols; cdx++) {
                CellStyleModel csm = jctable.getUniqueCellStyle(rdx, cdx);
//			 JCCellEditor jcce = csm.getCellEditor();
//			 JCTextFieldCellEditor jcce = csm.getCellEditor();
//			 JComponent jcce = csm.getCellEditor();
//			 jcce.setToolTipText("fred is here");
//			(csm.getCellEditor()).setToolTipText("fred is here");
////System.out.println("aTT: " + csm.getCellEditor());
                JCTextFieldCellEditor tfce = new JCTextFieldCellEditor();
//			tfce.setToolTipText("fred is here " + rdx + cdx);
////System.out.println("aTT: " + cdx + " " + eR[cdx].getToolTipText());
                tfce.setToolTipText(eR[cdx].getToolTipText());
                csm.setCellEditor(tfce);
                jctable.setCellStyle(hdrRows, bodCols - 1, csm);
            }
        }
    }

    /**
     * *********************************************************************
     * wjr
     */
    private void makeSpan(String[][] labelArray, int bodCols) {
        int crx;		// current row
//	int nrx;
        int ccx;		// current col
//	int ncx;
        int scx;		// start col

        super.makeSpan(labelArray, labelArray.length, jctable);
        /*	// test to span col
         JCCellRange spanrange = new JCCellRange(0, 0, 0, bodCols);
         try {
         jctable.addSpannedRange(spanrange);
         } catch (java.lang.IllegalArgumentException e) {
         }

         // start at one since we already spanned top row
         for (crx = 1; crx < labelArray.length; crx++) {
         String lastHdr = "";
         //		for (ccx = 0, scx = -1; ccx < labelArray[crx].length; ccx++) {
         for (ccx = 2, scx = 1; ccx < labelArray[crx].length; ccx++) {
         ////System.out.println("mS: " + crx + " " + ccx + " " + labelArray[crx][ccx]);
         if (labelArray[crx][ccx].trim().equals("~*R")) {
         //System.out.println("G_mS: " + lastHdr);
         labelArray[crx][ccx] = lastHdr;
         continue;
         }
         lastHdr = labelArray[crx][ccx];
         if (scx != ccx - 1) {
         ////System.out.println("G_mS: " + crx + "," + ccx + "," + nrx + "," + crx);
         // subtract 1 from rows because first row of labels is
         // handled by system
         spanrange = new JCCellRange(crx, scx, crx, ccx - 1);
         ////System.out.println("G_mS: " + spanrange);
         try {
         jctable.addSpannedRange(spanrange);
         } catch (java.lang.IllegalArgumentException e) {
         //System.err.println("overlapping spanning ranges " + spanrange);
         }
         }
         scx = ccx;
         }
         }
         Collection col = jctable.getSpannedRanges();
         for (Iterator coli = col.iterator(); coli.hasNext(); ) {
         //System.out.println("G_mS: " + coli.next());
         }*/
    }

    /**
     * *********************************************************************
     * wjr
     */
    /**
     * testing doc of setHeight
     *
     * @title xxxx
     * @param rh
     */
    @Override
    public void setHeight(int rh) /*
     * testing doc of setHeight 3
     * */ {
        jctable.setPixelHeight(JCTableEnum.ALLCELLS, rh);
    }
    /*
     * testing doc of setHeight 2
     * */
    /**
     * *********************************************************************
     * wjr
     */
    private int tw = 600;

    /**
     *
     * @return
     */
    @Override
    public Dimension getPreferredSize() {
        Dimension d = jctable.getPreferredSize();
        tw += 20;
        d.width = tw;
        Dimension p = getParent().getParent().getSize();
////System.out.println("gPS: called " + d + super.getSize());
////System.out.println("gPS: called " + d + getParent().getSize());
        if (p.width > 20) {
            d.width = p.width - 20;
        }
////System.out.println("gPS: p " + p.width + " d " + d.width);
        return d;
    }

    /**
     * wjr
     *
     * @return
     */
    @Override
    public Dimension getMaximumSize() {
        Dimension d = jctable.getMaximumSize();
////System.out.println("gMxS: called " + d);
        return d;
    }

    /**
     * wjr
     *
     * @return
     */
    @Override
    public Dimension getMinimumSize() {
//	Dimension d = jctable.getMinimumSize();
        Dimension d = new Dimension(300, 25);
        d.width = getParent().getSize().width - 40;
////System.out.println("gMnS: called " + d + getParent().getSize());
        return d;
    }
    /**
     * *********************************************************************
     * wjr
     */
    private JTextField cellEditor = null;
    private String oldValue = null;
    private int editRow = -1;

    /**
     * wjr
     *
     * @param event
     */
    @Override
    public void beforeEditCell(JCEditCellEvent event) {
        Util.debugPrint(true, "edit row " + event.getRow());
        cellEditor = null;
    }

    /**
     * wjr
     *
     * @param event
     */
    @Override
    public void editCell(JCEditCellEvent event) {
        ////System.out.println("eC:");
        Component c = event.getEditingComponent();
        if (c instanceof JTextField) {
            cellEditor = (JTextField) c;
            if (oldValue == null) {
                oldValue = cellEditor.getText();
            }
            cellEditor.selectAll();
        }
        editRow = event.getRow();
        Util.debugPrint(true, "current row " + editRow);
    }

    /**
     * wjr
     *
     * @param event
     */
    @Override
    public void afterEditCell(JCEditCellEvent event) {
        ////System.out.println("aEC: " + " row " + event.getRow() + " col " + event.getColumn()
//						   + " " + ((cellEditor != null) ? cellEditor.getText() : "!none"));
        if (cellEditor != null) {
            if (!inputRecord.updateRecordFromGrid(event.getColumn(), event.getRow(),
                    inputType, cellEditor.getText())) {
                dataSource.setTableDataItem(oldValue,
                        event.getRow(), event.getColumn());
            }
//		cellEditor.setText(oldValue);
//		cellEditor.validate();
        }
        cellEditor = null;
        oldValue = null;

    }

    /**
     * wjr
     *
     * @param e
     */
    @Override
    public void actionPerformed(ActionEvent e) {
//System.out.println("aP:");
    }
    /**
     * *********************************************************************
     * wjr
     */
//Instead of having a single vector that will contain the row values that
// are copied or cut, we use a array of vectors - neha
//private	Vector	lineBuffer = null;
    private List<Vector<String>> lineBuffers = null;

    /**
     * *********************************************************************
     * wjr
     */
    private void setRowLabels(int hdrRows, int bodRows) {
//System.out.println("sRL: ");
        String[] labels = new String[bodRows + hdrRows];
        for (int idx = 0; idx < hdrRows; idx++) {
            labels[idx] = " ";
        }
        for (int idx = 0; idx < bodRows; idx++) {
            labels[idx + hdrRows] = " " + (idx + 1);
        }
        dataSource.setRowLabels(labels);
    }

    /**
     * *********************************************************************
     * wjr
     */
    /*
     public	void	deleteRow()

     {
     if (editRow > -1) {
     dataSource.deleteRows(editRow, 1);

     bodRows--;
     setRowLabels(hdrRows, bodRows);
     inputRecord.rowsChanged(bodRows, this);
     }
     }
     */
    /**
     * *********************************************************************
     * wjr
     */
    public void copyRow() {
        Vector<String> tmpBuffer;
        if (!checkSelection(true)) {
            return;
        }
        //System.out.println("CopyRow:startRow value:"+startRow+" endRow:"+endRow);

        //Use startRow - value of the row that has been selected
        // not the editRow which is for selecting cells - neha
        if (startRow > -1) {
            Util.debugPrint(true, "copy row " + startRow);
            Vector<Vector<String>> cells = Caster.<Vector<Vector<String>>>cast(dataSource.getCells());
            //lineBuffer = new Vector();
            int range = endRow - startRow + 1;
            lineBuffers = new ArrayList<>(range);
            for (int i = 0; i < range; i++) {
                lineBuffers.add(new Vector<String>());
            }
            int k = 0;
            for (int i = startRow; i <= endRow; i++, k++) {
                tmpBuffer = cells.elementAt(i);
                for (int idx = 0; idx < tmpBuffer.size(); idx++) {
                    String str = tmpBuffer.elementAt(idx);
                    Util.debugPrint(true, "copy row " + str);
                    //lineBuffer.add(new String(str));
                    lineBuffers.get(k).add(str);
                }
            }//end of outer for loop
        }
    }

    /**
     * *********************************************************************
     * joelevin
     */
    public void deleteRow() {
        if (!checkSelection(true)) {
            return;
        }
        if (startRow >= hdrRows) {
            Util.debugPrint(true, "delete row " + startRow);
            int range = endRow - startRow + 1;
            dataSource.deleteRows(startRow, range);
            bodRows = bodRows - range;
        }
        setRowLabels(hdrRows, bodRows);
        inputRecord.rowsChanged(bodRows, this);
    }

    /**
     * *********************************************************************
     * wjr
     */
    public void cutRow() {
        if (!checkSelection(true)) {
            return;
        }
        //System.out.println("CutRow:startRow value:"+startRow+" endRow:"+endRow);
        //Use startRow - value of the row that has been selected
        // not the editRow which is for selecting cells - neha
        if (startRow > -1) {
            Util.debugPrint(true, "cut row " + startRow);
//          Vector cells = dataSource.getCells();
//          lineBuffer = (Vector) cells.elementAt(editRow);
            copyRow();
            deleteRow();
        }
    }

    /**
     * *********************************************************************
     * wjr
     */
    public void pasteBeforeRow() {
        if (!checkSelection(true)) {
            return;
        }

        //System.out.println("PasteBeforeRow:startRow value:"+startRow+" endRow:"+endRow);
        if (startRow > -1 && lineBuffers != null) {
            Util.debugPrint(true, "paste row " + startRow + " " + lineBuffers.get(0).elementAt(0));
            int k = startRow;
            for (Vector<String> lineBuffer : lineBuffers) {
                dataSource.addRow(k, " ", createCopy(lineBuffer));
                k++;
                bodRows++;
            }
            setRowLabels(hdrRows, bodRows);
            inputRecord.rowsChanged(bodRows, this);
        }
    }

    /**
     *
     */
    public void pasteAfterRow() {
        int offset = 1;
        if (bodRows > 0 && !checkSelection(true)) {
            return;
        } else if (bodRows <= 0) {
            startRow = hdrRows;
            offset = 0;
        }

        //System.out.println("PasteAfterRow:startRow value:"+startRow+" endRow:"+endRow);
        if (startRow > -1 && lineBuffers != null) {
            Util.debugPrint(true, "paste row " + startRow + " " + lineBuffers.get(0).elementAt(0));
            int k = startRow;
            for (Vector<String> lineBuffer : lineBuffers) {
                dataSource.addRow(k + offset, " ", createCopy(lineBuffer));
                k++;
                bodRows++;
            }
            setRowLabels(hdrRows, bodRows);
            inputRecord.rowsChanged(bodRows, this);
        }
    }

    private <T> Vector<T> createCopy(Vector<T> vector) {
        if (vector == null) {
            return null;
        }
        Vector<T> result = new Vector<>(vector.size());
        for (T o : vector) {
            result.add(o);
        }
        return result;
    }

    /**
     * *********************************************************************
     * wjr
     */
//This method is obsolete - should be deleted later - Neha, 04/19/05
    public void insertRow() {
        if (editRow > -1) {
            Vector<Vector<String>> cells = Caster.<Vector<Vector<String>>>cast(dataSource.getCells());
            Vector<String> cello = cells.elementAt(editRow);
            Vector<String> newVec = new Vector<>();
            for (int idx = 0; idx < cello.size(); idx++) {
                String str = cello.elementAt(idx);
                newVec.add(str);
            }
            dataSource.addRow(editRow, " ", newVec);
            inputRecord.rowsChanged(++bodRows, this);
            setRowLabels(hdrRows, bodRows);
//		dataSource.setNumRows(dataSource.getNumRows() + 1);
        }
    }

    /**
     *
     */
    public void insertRowAfter() {
        int offset = 1;
        if (bodRows > 0 && !checkSelection(true)) {
            return;
        } else if (bodRows <= 0) {
            startRow = hdrRows;
            offset = 0;
        }

        if (startRow > -1) {
            Vector<Vector<String>> cells = Caster.<Vector<Vector<String>>>cast(dataSource.getCells());
            Vector<String> cello = cells.elementAt(startRow);
            Vector<String> newVec = new Vector<>();
            for (String cello1 : cello) {
                newVec.add(String.valueOf(Double.NaN));
            }
            dataSource.addRow(startRow + offset, " ", newVec);
            inputRecord.rowsChanged(bodRows++, this);
            setRowLabels(hdrRows, bodRows);
        }
    }

    /**
     *
     */
    public void insertRowBefore() {

        if (!checkSelection(true)) {
            return;
        }

        if (startRow > -1) {
            Vector<Vector<String>> cells = Caster.<Vector<Vector<String>>>cast(dataSource.getCells());
            Vector<String> cello = cells.elementAt(startRow);
            Vector<String> newVec = new Vector<>();
            for (String cello1 : cello) {
                newVec.add(String.valueOf(Double.NaN));
            }
            dataSource.addRow(startRow, " ", newVec);
            inputRecord.rowsChanged(++bodRows, this);
            setRowLabels(hdrRows, bodRows);
        }
    }

    /**
     * wjr
     *
     * @param row
     * @param col
     * @param val
     */
    public void updateValue(int row, int col, String val) {
//System.out.println("uV : " + row + " " + col + " " + val);
        Vector<Vector<String>> cells = Caster.<Vector<Vector<String>>>cast(dataSource.getCells());
        Vector<String> cello = cells.elementAt(row + hdrRows);
        cello.setElementAt(val, col);
    }

    /**
     * wjr
     *
     * @return
     */
    public int getHeaderRowCount() {
        return hdrRows;
    }

    /**
     * wjr
     *
     * @param row
     * @param col
     * @return
     */
    public String getValue(int row, int col) {

        Vector<Vector<String>> cells = Caster.<Vector<Vector<String>>>cast(dataSource.getCells());
        Vector<String> cello = cells.elementAt(row + hdrRows);
        try {
            return cello.elementAt(col);
        } catch (java.lang.ArrayIndexOutOfBoundsException e) {
            return "???";
        }
    }
    /**
     * *********************************************************************
     * neha
     */
    int startRow = -1;
    int endRow = -1;
    int startCol = -1;
    int endCol = -1;
    boolean showPopupMenu = false;

    /**
     *
     * @param e
     */
    @Override
    public void select(JCSelectEvent e) {
        showPopupMenu = false;
    }

    /**
     *
     * @param e
     */
    @Override
    public void afterSelect(JCSelectEvent e) {
        startRow = Math.min(e.getStartRow(), e.getEndRow());
        endRow = Math.max(e.getStartRow(), e.getEndRow());
        startCol = e.getStartColumn();
        endCol = e.getEndColumn();

        //This becomes true only after the entire row is selected
        //If only one or two rows are selected, then it remains false - neha
        showPopupMenu = true;
    }

    /**
     *
     * @param e
     */
    @Override
    public void beforeSelect(JCSelectEvent e) {
    }

    /**
     * neha
     *
     * @return
     */
    //Return true if the entire row is selected
    public boolean showPopup() {
        boolean retValue = false;
        // //System.out.println("showPopupMenu value:"+showPopupMenu);
        if (showPopupMenu && checkSelection(false)) {
            /* Only when the entire row is selected, the startCol and
             * endCol both have a value of -1; If multiple range of cells are
             * selected, then startCol and endCol will have a positive value
             * We take advantage of this here to pick out those instances where only
             * the entire row is selected, to show the popup menu - neha
             */
            //   //System.out.println("startCol:"+startCol+" endCol:"+endCol);
            if (startCol == -1 && endCol == -1) {
                retValue = true;
            }
        }
        return retValue;
    }

    /**
     *
     * @return
     */
    public boolean showHeaderPopup() {
        // //System.out.println("showPopupMenu value:"+showPopupMenu);
        return false;

    }

    /**
     *
     * @param okayIfNoData
     * @return
     */
    public boolean showPopup(boolean okayIfNoData) {

        if (bodRows > 0 && showPopupMenu && checkSelection(false)) {
            /* Only when the entire row is selected, the startCol and
             * endCol both have a value of -1; If multiple range of cells are
             * selected, then startCol and endCol will have a positive value
             * We take advantage of this here to pick out those instances where only
             * the entire row is selected, to show the popup menu - neha
             */
            //   //System.out.println("startCol:"+startCol+" endCol:"+endCol);
            if (startCol == -1 && endCol == -1) {
                return true;
            }
        } else if (bodRows <= 0) {
            return true;
        }

        return false;

    }

    /**
     * *********************************************************************
     * neha
     */
    /**
     * wjr
     *
     * @param l
     */
    @Override
    public void addMouseListener(MouseListener l) {
        super.addMouseListener(l);
        jctable.addMouseListener(l);
    }

    /**
     * wjr
     *
     * @return
     */
    public int getCurrentRow() {
        Util.debugPrint(true, "current cell " + jctable.getCurrentCell());
        return jctable.getCurrentRow();
    }

    /**
     * wjr
     *
     * @param msgFlg
     * @return
     */
    public boolean checkSelection(boolean msgFlg) {
        Vector<JCCellRange> scv = getSelectedRows();
        if (scv == null || scv.isEmpty()) {
            if (msgFlg) {
                JOptionPane.showMessageDialog(Util.getParentJFrame(this), "No row selected",
                        "Error changing layers", JOptionPane.ERROR_MESSAGE);
            }
            return false;
        }

        for (JCCellRange range : scv) {
            for (int i = 0; i < hdrRows; i++) {
                if (range.inRowRange(i)) {
                    if (msgFlg) {
                        JOptionPane.showMessageDialog(Util.getParentJFrame(this),
                                "Invalid row selected", "Error changing layers", JOptionPane.ERROR_MESSAGE);
                    }
                    return false;
                }
            }
        }

        return true;
    }

    @SuppressWarnings("unchecked")
    private Vector<JCCellRange> getSelectedRows() {

        Collection<JCCellRange> sc = jctable.getSelectedCells();
        if (sc == null) {
            return null;
        }
        int numCols = jctable.getNumColumns();

        //     //System.out.println("Number of Rows:"+jctable.getNumRows());
        //     //System.out.println("Number of Visible Rows:"+jctable.getNumVisibleRows());
        //     //System.out.println("Number of Columns:"+jctable.getNumColumns());
        //     //System.out.println("Number of Visible Columns:"+jctable.getNumVisibleColumns());
        Vector<JCCellRange> scv = new Vector<>();
        for (JCCellRange jccr : sc) {
            /* Added by Sada, Jun 30, 2003 */
            /* Note: Due to some reasons, there are invalid entries sometimes in the collection such as
             * Row 1, Col -1, R1, C 214748367
             */
            /*
             if( (jccr.start_column < 0) || (jccr.end_column < 0) || (jccr.start_row < 0) || (jccr.end_row < 0) )
             continue;
             */
            /*	End, additions by Sada, Jun 30, 2003 */
            //     //System.out.println("Start Column:"+jccr.start_column+"  End Column:"+jccr.end_column);
            //     //System.out.println("Start Row:"+jccr.start_row+"  End Row:"+jccr.end_row);
            if (jccr.start_row < 0 || jccr.end_row < 0) {
                continue;
            }
            if (jccr.start_column < 0 || jccr.end_column >= numCols) {
                jccr = new JCCellRange(jccr.start_row, 0, jccr.end_row, numCols);
            }

            scv.add(jccr);
        }

        Collections.sort(scv, new CompareRange());

        return scv;
    }

    /**
     *
     * @param readonly
     */
    public void setReadonly(boolean readonly) {
        for (Object o : jctable.getCellStyles()) {
            JCCellStyle style = (JCCellStyle) o;
            style.setEditable(!readonly);
        }
    }

    private static class CompareRange extends JCCellRange implements Comparator<JCCellRange> {

        private static final long serialVersionUID = 1L;

        @Override
        public boolean equals(Object to) {
            if (!(to instanceof JCCellRange)) {
                return false;
            }
            return this.start_row == ((JCCellRange) to).start_row;
        }

        @Override
        public int compare(JCCellRange o1, JCCellRange o2) {
            return o2.start_row - o1.start_row;
        }

        @Override
        public int hashCode() {
            int hash = 3;
            return hash;
        }
    }
    /**
     * *********************************************************************
     * wjr
     */
}
