/* Title:		CropDlg.java
 * Version	
 * Author		Sada, Manmohan K Uttarwar
 * Company: USDA-ARS
 * Date:    July, 2003, April 2005
 */
package usda.weru.mcrew;

import java.awt.*;
import java.awt.event.*;
import de.schlichtherle.truezip.file.TFile;
import javax.swing.*;
import java.util.*;

import com.klg.jclass.cell.editors.*;
import com.klg.jclass.cell.renderers.*;
import com.klg.jclass.cell.*;
import com.klg.jclass.table.*;
import com.klg.jclass.table.data.*;
import java.util.List;
import javax.help.CSH;
import javax.help.HelpBroker;
import javax.help.HelpSet;
import usda.weru.util.*;

/**
 * CropDlg screen displays the values of all parameters of the selected crop.
 * Paramter values can also be modified from here. Also, modified values can
 * be saved as a new crop.
 */
public class CropDlg extends usda.weru.mcrew.gui.CropDlg_n {

    private static final long serialVersionUID = 1L;

    Hashtable<String, Vector<ParamChanger>> c_paramChangers;
    Hashtable<String, String> c_tooltipTable;
    static final int MIN_WIDTH = 685;
    static final int MIN_HEIGHT = 550;
    static int mySetDataTabCalls = 0;
    int sideOffset = 10;
    int betComponentOffSet = 5;    //Hashtable cValues;
    private CropObject mCropObject; // holds a copy (clone) of Operation Object passed to the constructor
    private CropMeta mCropMeta; // holds a copy (clone) of the crop_defn.xml info
    CropObject mOriginalCrop; // Holds the operation object passed. This is updated only if user clicks OK.
    CropObject mSaveCropObject; // holds the crop object with new changes for save as
    String mCropName;
    ParamJCTable mParamTable;
    /**
     * This vector stores the category names from the crop display file in
     * which all the parameters are categorized to be displayed under the
     * respective tab in crop dialog screen.
     */
    public List<String> cnVec = new Vector<String>();

    /**
     * Each parameter display element in a particular category of crop has a
     * paramname and these paramnaes a re being stored in this hashtable.
     */
    public Map<String, List<String>> cParams = new Hashtable<String, List<String>>();
    /**
     * Stores the number that tells how many crop categories we have currently.
     */
    public int numCategory;
    /**
     * This vector hold the paramJCTable objects that contain the parameter
     * names, corresponding values and units those values are in.
     */
    private Vector<ParamJCTable> tabTables = new Vector<ParamJCTable>();
    private Hashtable<String, ParamJCTable> tabTableMap = new Hashtable<String, ParamJCTable>();
    
    /**
     * This hashmap stores the map of tab table index to tab index, so we can treat
     * some tabs as "invisible"
     */
    private HashMap<Integer, Integer> tabMap = new HashMap<Integer, Integer>();
    
    private Table origin; //This is just so we can activate checkData upon exit.
    /**
     * Stores the parameter names existing under each category for a particular
     * crop.
     */
    public Vector<String> myParamVec = new Vector<>();
    /**
     *  The foreground color of text when the cell is selected f or editing
     *  purpose.
     */

    /**
     * Name value separator
     */
    public static String sIdNameSeparator = ":";
    /**
     * String that tells when there are no available parameters. Used during
     * debugging and to catch the exception
     */
    public static String sNoParameters = "No Prameters";
    /**
     * Flag that indicates if the data in the table was changed which helps in
     * saving the values in the underlying datastructure.
     */
    protected boolean dataChanged = false;
    /**
     * Flag that indicates if the data in the notes of the Crop Drill Down Screen was
     * changed which helps in saving the values in the underlying datastructure - neha
     */
    protected boolean notesDataChanged = false;
    /**
     * Flag that indicates to refresh the MCREW screen table based on changes in
     * the crop dialog table data manipulation.
     */
    public String refreshMcrewScreen = "false";
    ManageData c_manage;
    RowInfo c_row;

    /**
     *
     */
    protected TablePanel c_mcrew;

    /**
     * Constructor that creates and initializes the dialog box showing the
     * different tabs wit hcategory names and the data for that category from
     * the selected crop object with pCropName.
     * @param tab The container in which this crop dialog sits
     * @param pCropName Name of the crop whose data will be pulled
     * @param pCropObject The crop object storing the metadata for crop with name
     * pCropName
     * @param manage
     * @param mcrew
     * @param row
     */
    public CropDlg(Table tab, String pCropName, CropObject pCropObject,
            ManageData manage, RowInfo row, TablePanel mcrew) {
        //mNameListModel = new DefaultListModel();
        super(Util.getParentJFrame(tab));
        origin = tab;

        c_mcrew = mcrew;
        c_manage = manage;
        c_row = row;

        mOriginalCrop = pCropObject;
//		mCropObject = (CropObject)pCropObject.clone();
        mCropMeta = pCropObject.getMeta();
        mCropObject = pCropObject;
        mSaveCropObject = mCropObject;
        JTF_cropName.setText(pCropName);
        mParamTable = new ParamJCTable();
        //Intialize these booleans to false. Since they are static variables
        //their values will persist between different instantiations of CropDlg
        //till Weps is closed - neha
        dataChanged = false;
        notesDataChanged = false;
        initialize();
        Util.loadToolTips((Container) this, new TFile("mcrew_cfg", "mcrewtooltips.cfg"));

    }

    /**
     * This method brings the table up in the crop dialog and populates it with
     * the data that each tab needs to be populated from that particular crop
     * object.
     */
    public void initialize() {
        JP_param.getViewport().setView(mParamTable);
        c_paramChangers = new Hashtable<String, Vector<ParamChanger>>();
        //OperationParamPanel.add(mOperationTable);
        showTable();
        populateTabs();
        addHelp();
        c_tooltipTable = Util.loadToolTipsTable(new TFile("mcrew_cfg", "mcrewtooltips.cfg"));

    }
    
    /**
     * This method checks the new data to be put in, indicates a change of cell
     * color if necessary.
     * 
     * For initialization.
     * @param row
     * @param catParams
     * @return 
     */
    private InputLimits.TableStatus checkDataCell(int row, List<String> catParams)
    {
        String name = catParams.get(row);
        Parameter attempt = mCropObject.getParameter(name);
        if(attempt == null) return InputLimits.TableStatus.OKAY;
        String value = attempt.get(XMLConstants.svalue);
        if(value == null) return InputLimits.TableStatus.OKAY;
        ParameterMeta limits = mCropMeta.getParameterMeta(name);
        //We want to completely ignore the formatting of the cell if we have multiline
        //text, as the cell should render as a choice list.
        if(limits.getGroupAttribute(name, XMLConstants.svalueattribute).
                equals(XMLConstants.schoice)) return InputLimits.TableStatus.CHOICE;
        //We want to completely ignore the formatting of the cell if we have multiline
        //text, as the cell should render as a button.
        if(limits.getGroupAttribute(name, XMLConstants.svalueattribute).
                equals(XMLConstants.smultiline)) return InputLimits.TableStatus.CHOICE;
        //We only want to try and bound an item if it is listed under decomp parms
        if(mCropObject.getParameter("idc") != null)
        {
            if(mCropObject.getParameter("idc").getValue().equals("0") && !mCropMeta.getDecompNames().contains(name))
                return InputLimits.TableStatus.OKAY;
        }
        InputLimits limiter = limits.getLimits();
        //If the display is in English Units, we want to convert it to metric for the tests.
        if(MCREWConfig.getDisplayUnit() == 1) value = limits.convertToPrimaryUnits(value);
        InputLimits.TableStatus currentCellStatus = limiter.evaluateInput(value);
        return currentCellStatus;
    }
    
    /**
     * This method checks the new data to be put in, indicates a change of cell
     * color if necessary.
     * 
     * For later edits.
     * @param row
     * @param catParams
     * @return 
     */
    private InputLimits.TableStatus checkDataCell(String value, String paramName)
    {
        String text = value;
        if(value == null) return InputLimits.TableStatus.OKAY;
        ParameterMeta limits = mCropMeta.getParameterMeta(paramName);
        //We want to completely ignore the formatting of the cell if we have multiline
        //text, as the cell should render as a choice list.
        if(limits.getGroupAttribute(paramName, XMLConstants.svalueattribute).
                equals(XMLConstants.schoice)) return InputLimits.TableStatus.CHOICE;
        //We want to completely ignore the formatting of the cell if we have multiline
        //text, as the cell should render as a button.
        if(limits.getGroupAttribute(paramName, XMLConstants.svalueattribute).
                equals(XMLConstants.smultiline)) return InputLimits.TableStatus.CHOICE;
        //We only want to try and bound an item if it is listed under decomp parms
        if(mCropObject.getParameter("idc") != null)
        {       
            if(mCropObject.getParameter("idc").getValue().equals("0") && !mCropMeta.getDecompNames().contains(paramName))
                        return InputLimits.TableStatus.OKAY;
        }
        InputLimits limiter = limits.getLimits();
        //If the display is in English Units, we want to convert it to metric for the tests.
        if(MCREWConfig.getDisplayUnit() == 1) text = limits.convertToPrimaryUnits(value);
        InputLimits.TableStatus currentCellStatus = limiter.evaluateInput(text);
        return currentCellStatus;
    }

    /**
     * Generic adding of help.
     */
    private void addHelp() {
        addCSH(Help.getHelpSet());
    } //end of addhelp()

    /**
     * Adding help with a HelpSet parameter passed in.
    */
    private void addCSH(HelpSet hs) {
        HelpBroker hb = hs.createHelpBroker();

        hb.enableHelpKey(getRootPane(), "crop_intro_html", hs);

        JB_help.addActionListener(new CSH.DisplayHelpAfterTracking(hs, "javax.help.Popup", null));

        //Add help ids to the components
        CSH.setHelpIDString(JTP_main, "crop_drill_table_html");
        CSH.setHelpIDString(JP_specs, "crop_drill_cropname_html");
        CSH.setHelpIDString(JP_toolbar, "crop_drill_toolbar_html");

        CSH.setHelpIDString(JB_cancel, "crop_toolbar_cancel_html");
        CSH.setHelpIDString(JB_saveAs, "crop_toolbar_save_html");
        CSH.setHelpIDString(JB_help, "crop_toolbar_help_html");
        CSH.setHelpIDString(JB_close, "crop_toolbar_return_html");

    }//end of addCSH

    /**
     *
     * @param paramName
     * @param newValue
     */
    public void notfiyTablesOfChange(String paramName, Object newValue) {
        Vector<ParamChanger> paramChangers = c_paramChangers.get(paramName);
        //If it the vector is null we do nothing
        if (paramChangers == null) {
            return;
        }
        //loop over all the changers and update the values
        for (ParamChanger paramChanger : paramChangers) {
            paramChanger.updateValue(newValue);
        }

    }

    /**
     *
     * @param paramName
     * @param dataSource
     * @param row
     * @param col
     * @param type
     */
    public void registerParamOnTable(String paramName,
            JCEditableVectorDataSource dataSource, int row, int col, int type) {
        Vector<ParamChanger> paramChangers = c_paramChangers.get(paramName);
        //If it the vector is null we make a new one
        if (paramChangers == null) {
            paramChangers = new Vector<ParamChanger>();
            c_paramChangers.put(paramName, paramChangers);
        }
        ParamChanger tempChanger = new ParamChanger(dataSource, row, col, type);
        paramChangers.add(tempChanger);
    }

    /**
     * Displays the table under different category tabs.
     */
    public void showTable() {
        mParamTable.clear();
        mParamTable.setData(mCropObject);

        invalidate();
        repaint();
        //JP_parameter
        //mParamTable.setVisible(false);
    }
   
    /**
     * Method to accumulate the table status of all the ParamJCTables.
     */
    public InputLimits.TableStatus accumulateTableStatus()
    {
        InputLimits.TableStatus accumulate = InputLimits.TableStatus.OKAY;
        for(ParamJCTable table : tabTables)
        {
            InputLimits.TableStatus current = table.getTotalStatus();
            if(accumulate.lessThan(current)) accumulate = current;
        }
        return accumulate;
    }
    
    /**
     * This method polls all of the ParamJCTables to highlight the ones out of
     * bounds.
     */
    @Override
    protected void tabs()
    {
        if(tabTables != null)
        {
            for(int index = 0; index < tabTables.size(); index ++)
            {
                Integer tab = tabMap.get(index);
                if(tab == null) continue;
                if(tabTables.get(index).getTotalStatus() == InputLimits.TableStatus.NOSAVE) 
                    JTP_main.setBackgroundAt(tab, Color.MAGENTA);
                else if(tabTables.get(index).getTotalStatus() == InputLimits.TableStatus.WARNSAVE)
                    JTP_main.setBackgroundAt(tab, Color.YELLOW);
                else JTP_main.setBackgroundAt(tab, null);
            }
        }
    }

    /**
     * Method populates all the tabs with corresponding meta data with the
     * paramname, its value and the units in which those values are displayed.
     */
    public void populateTabs() {

        cnVec = mCropObject.getCategoryNames();
        cParams = mCropObject.getCategoryParams();
        numCategory = cnVec.size();
        List<String> paramVec;

        int lastFree = 0;//stores the index where a tab will be added.
        for (int i = 0; i < numCategory; i++) {
            String cName = cnVec.get(i);
            paramVec = cParams.get(cName.trim());

            if (paramVec.isEmpty()) {
                //System.out.println("setDataTab : VECTOR paramVec is EMPTY");
            }

            /**paramVec is the vector that contains the parameter objects for a given category.
             * Check that atleast one parameter object associated with the category is not null - so that
             * it justifies the cause of having a tab for that category in the drilldown screen - neha
             */
            boolean setTabCategory = false;
            for (String paramName : paramVec) {
                Parameter param = mCropObject.getParameter(paramName);
                if (param != null) {
                    setTabCategory = true;
                    break;
                }
            }
            if (setTabCategory == true) {
                JPanel tabPanel = new JPanel();
                tabPanel.setLayout(new BorderLayout());
                JScrollPane JSP_viewArea = new JScrollPane();
                //Pass the CropDlg Reference to the ParamJCTable, so that the 
                // Crop Notes will have a reference to the parent Dialog - neha
                ParamJCTable myTable = new ParamJCTable(this, cName);
                myTable.clear();
                JSP_viewArea.getViewport().setView(myTable);
                //if(visible.equals("true") ){
                tabPanel.add(JSP_viewArea, BorderLayout.CENTER);
                //Set the "allParamsHidden" attribute for this category of the CropObject 
                //to true before setting the parameters in this category - neha
                mCropObject.allParamsHidden = true;
                myTable.setDataTab(mCropObject, paramVec);
                myTable.invalidate();
                myTable.setName(cName);
                tabTables.add(myTable);
                tabTableMap.put(myTable.getCategoryName(), myTable);
                //System.out.println("CropDlg: populateTabs" + " Category Name = " + cName + ", Is Visible = " + visible );
                //If atleast one of the parameters has a Viewable/Editable display
                //attribute, then add that tab(category) to the drilldown screen - neha
                if (mCropObject.allParamsHidden == false) {
                    JTP_main.addTab(cName, tabPanel);
                    tabMap.put(i, lastFree ++);
                }

                //}
                //JTP_main.remove(JP_parameters);
                invalidate();
                repaint();
            } else {
                //atleast one category for this crop object is empty
                mCropObject.categoryEmpty = true;
            }// end of if(setTabCategory == true)
        }//end of for loop on cnVec size
        JTP_main.removeTabAt(0);

    }

    /**
     * Saves all of the data back into the Crop Object.
     * @param pCropObject 
     */
    @SuppressWarnings("fallthrough")
    void saveCropData(CropObject pCropObject) {
                //System.out.println("====== CROP DRILL DOWN SAVE ======");
        //Check allowSave status
        switch(accumulateTableStatus())
        {
            case NOSAVE:
                JOptionPane.showMessageDialog(null, "Unable to save:\nSome data out of limits.",
                mCropObject.getCropName(), JOptionPane.INFORMATION_MESSAGE);
//                scrollToTab();
                break;
            case WARNSAVE:
                JOptionPane.showMessageDialog(null, "Warning:\nSome data out of recommended limits.",
                mCropObject.getCropName(), JOptionPane.INFORMATION_MESSAGE);
            default:
                cParams = pCropObject.getCategoryParams();
                for (int i = 0; i < JTP_main.getTabCount(); i++) {
                    String cName = JTP_main.getTitleAt(i);
                    //System.out.println("Category Name : " + cName  );
                    myParamVec = (Vector<String>) cParams.get(cName.trim());
                    //System.out.println("  myParamVec is Assigned :" + myParamVec.isEmpty() );
                    ParamJCTable table = tabTableMap.get(cName);
                    if (table != null) {
                        table.saveTabDataSource(pCropObject, myParamVec);
                    } else {
                        throw new RuntimeException("Trying to save to a table that does not exist. '" + cName + "'");
                    }
                }
                dataChanged = false;
                notesDataChanged = false;
            }
    }

    @Override
    public void closeWindow_actionPerformed(java.awt.event.WindowEvent evt) {
        closeWindow();
        origin.checkData();
    }

    @Override
    public void JBClose_actionPerformed(java.awt.event.ActionEvent event) {
        closeWindow();
    }

    void closeWindow() {
        //Make sure every edit has been commited.
        for (Object o : tabTables) {
            JCTable table = (JCTable) o;
            table.commitEdit(true);
        }
        //If any data has changed in the drill down screen, then ask if these
        //changes have to be saved to the new crop - neha
        int option = -200;
        if (dataChanged == true || notesDataChanged == true) {
            option = JOptionPane.showConfirmDialog(this, "Save changes made to the current Crop Info? ");
            //System.out.println("CropDlg : closeWindow -- OPTION is : " + option );
            switch (option) {
                case JOptionPane.CANCEL_OPTION:
                    break;
                case JOptionPane.YES_OPTION:
                    saveCropData(mCropObject);
                    mOriginalCrop = mCropObject;
                    c_manage.fireRowChanged(c_row);
                    break;
                case JOptionPane.NO_OPTION:
                    break;
            }
        }
        //If neither Cancel nor close option was selected, then close the window
        //If the table has a nosave status, we don't want them to close after trying to save.
        if ((option != JOptionPane.CANCEL_OPTION && option != JOptionPane.CLOSED_OPTION)
                || (option == JOptionPane.YES_OPTION && accumulateTableStatus() == InputLimits.TableStatus.NOSAVE)) {
            this.setVisible(false);
            dispose();
        }
    }

    /**
     * Returns the crop object that might have the most updated data based on the modifications
     * that happened on the various tab of each category visible on the crop dialog screen.
     * @return The cropObject holding the most updated data.
     */
    public CropObject getCropObject() {

        return mOriginalCrop;

    }

    @Override
    public void CancelButton_actionPerformed(java.awt.event.ActionEvent event) {
        this.setVisible(false);
        dispose();
    }
    
    //Saves the crop as a new file
    @Override
    @SuppressWarnings("fallthrough")
    public void SaveAsJButton_actionPerformed(java.awt.event.ActionEvent event) {
        int option = -1;
        //System.out.println("SaveAsJButton_actionPerformed:dataChanged:"+dataChanged+"  notesDataChanged:"+notesDataChanged);
        switch(accumulateTableStatus())
        {
            case NOSAVE:
                JOptionPane.showMessageDialog(null, "Unable to save:\nSome data out of limits.",
                mCropObject.getCropName(), JOptionPane.INFORMATION_MESSAGE);
//                scrollToTab();
                break;
            case WARNSAVE:
                JOptionPane.showMessageDialog(null, "Warning:\nSome data out of recommended limits.",
                mCropObject.getCropName(), JOptionPane.INFORMATION_MESSAGE);
            default:
            //If any data has changed in the drill down screen, then ask if these
            //changes have to be saved to the new crop - neha
            if (dataChanged == true || notesDataChanged == true) {
                option = JOptionPane.showConfirmDialog(this, "Save changes made to the current Crop Info? ");
                //System.out.println("CropDlg : SaveAsJButton_actionPerformed -- OPTION is : " + option );
                switch (option) {
                    case JOptionPane.CANCEL_OPTION:
                        return;
                    case JOptionPane.YES_OPTION:
                        mSaveCropObject = mCropObject;
                        saveCropData(mSaveCropObject);
                        mOriginalCrop = mCropObject;
                        c_mcrew.setDataChanged(true);
                        break;

                    case JOptionPane.NO_OPTION:
                        //Get a clone from the original crop.  We don't want to save mcrew's crop object.
                        mSaveCropObject = (CropObject) mOriginalCrop.clone();
                        //Save the data in the table to the cloned crop object
                        saveCropData(mSaveCropObject);
                        break;
                }
            }

            ////System.out.println("CropDLG : SAVE AS Button :" + WepsFileChooser.CROP);
            TFile cropDir = new TFile(MCREWConfig.getDirectoryName(XMLConstants.scrop));
            String cropDirPath = cropDir.getAbsolutePath();
            WepsFileChooser mfc = new WepsFileChooser(WepsFileChooser.Filetype.CROP, cropDirPath,
                    WepsFileChooser.SAVE);
            //set the tooltip of "home" button to "Home" instead of "Desktop"
            mfc.homeToolTip(mfc);

            mfc.setCurrentDirectory(cropDir); //new de.schlichtherle.truezip.file.File(ConfigData.INITIAL_DIR));

            mfc.setDialogTitle("Save a new Crop");
            if (mfc.showDialog(this) != JFileChooser.APPROVE_OPTION) {
                return;
            }
            String newFileName = null;
            try {
                newFileName = mfc.getSelectedFile().getCanonicalPath();

            } catch (java.io.IOException e) {
                System.err.println("OprnDlg:Save As(): error " + e);
                return;
            }
            //System.out.println("CropDlg : SaveAsJButton_actionPerformed : Filename is - - -  " + newFileName);
            if (!newFileName.endsWith(".crop")) {
                newFileName = newFileName + ".crop";
            }
            ////System.out.println("CropDlg : SaveAsJButton_actionPerformed : JUST Filename is - - -  " + newFileName1);
            mSaveCropObject.writeXMLFile(newFileName);
            MCREWConfig.getCropFileList().refreshFiles();
        }
    }

    @Override
    public void JBHelp_actionPerformed(java.awt.event.ActionEvent evt) {
    }

    @Override
    public void CropDlgN_componentResized(java.awt.event.ComponentEvent evt) {
        validate();
        Dimension size = evt.getComponent().getSize();

        if (size.getHeight() < MIN_HEIGHT) {
            size.height = MIN_HEIGHT;
        }
        if (size.getWidth() < MIN_WIDTH) {
            size.width = MIN_WIDTH;
        }

        this.setSize(size);
        size.height -= 50;
        size.width -= 25;
        JP_main.setSize(size);

        JP_toolbar.setSize((int) size.getWidth() - (2 * betComponentOffSet), 40);
        JP_toolbar.setLocation(betComponentOffSet, betComponentOffSet);

        JP_specs.setSize((int) size.getWidth() - (2 * betComponentOffSet), 30);
        JP_specs.setLocation(betComponentOffSet, (JP_toolbar.getHeight() + 2 * betComponentOffSet));

        int yLocation = (JP_toolbar.getHeight() + JP_specs.getHeight() + (5 * betComponentOffSet));
        size.height -= yLocation;
        size.width -= 15;
        JTP_main.setSize(size);
        size.height -= 15;
        size.width -= 15;
        JTP_main.setLocation(betComponentOffSet, yLocation - (2 * betComponentOffSet));
        JP_parameters.setSize(size);
        size.width -= 20;
        JP_cropData.setSize((int) size.getWidth(), ((int) size.getHeight() - (2 * betComponentOffSet)));
        JP_cropData.setLocation(sideOffset, (JP_specs.getHeight() + (2 * betComponentOffSet)));
        //JP_cropData.setVisible(false);
        JP_param.setSize((int) size.getWidth(), ((int) size.getHeight() - (3 * betComponentOffSet)));
        JP_param.setLocation(sideOffset, betComponentOffSet);

        validate();
        repaint();
    }

    static class ParamTableCSHManager implements CSH.Manager {

        private ParamJCTable c_table;

        public ParamTableCSHManager(ParamJCTable table) {
            c_table = table;
        }

        private void translateMouseEvent(MouseEvent me) {
            Object parent = me.getSource();
            Component comp = c_table;
            int x = 0;
            int y = 0;
            while (comp != parent) {
                x += comp.getX();
                y += comp.getY();
                comp = comp.getParent();
            }

            me.translatePoint(-x, -y);
        }

        @Override
        public String getHelpIDString(Object comp, AWTEvent evt) {
            if (comp != c_table) {
                return null;
            }
            try {
                if (evt instanceof MouseEvent) {
                    MouseEvent me = (MouseEvent) evt;
                    translateMouseEvent(me);
                    int row = c_table.YtoRow2(me.getY());

                    String paramName = c_table.c_catParams.get(row);
                    return paramName + "_html";
                } else {
                    return null;
                }
            } catch (Exception e) {
                return null;
            }
        }

        @Override
        public HelpSet getHelpSet(java.lang.Object comp, java.awt.AWTEvent e) {
            return Help.getHelpSet();
        }
    }

    class ParamJCTable extends JCTable implements JCEditCellListener, MouseMotionListener {

        private static final long serialVersionUID = 1L;

        public String mHeaderRow[] = {"Parameter", "Value", "Units"};
        int PROMPTCOLUMN = 0;
        int VALUECOLUMN = 1;
        int UNITSCOLUMN = 2;
        private String c_categoryName;
        //This is used to check if theres a need for saving data from VDataSource to the action object
        boolean mDataChanged = false;
        CropObject c_cropObject;
        List<String> c_catParams;
        JCEditableVectorDataSource mVDataSource;
        JCCellStyle mCellStyle, mUnHLimitCellStyle, mUnSLimitCellStyle, mValueCellStyle, mHLimitCellStyle, mSLimitCellStyle;
        JCStringCellEditor se;
        NotesCrop notes;
        CropDlg parentDlg;
        //This is the text that the notes button will be having - neha
        
        
        /**
         * Variables to store whether the Drill down can save, and offending cells
         */
        private InputLimits.TableStatus allowSave = InputLimits.TableStatus.OKAY;
        ArrayList<Integer> outHard = new ArrayList<Integer>();
        ArrayList<Integer> outSoft = new ArrayList<Integer>();
        ArrayList<String> outTab = new ArrayList<String>();
    

        public String getCategoryName() {
            return c_categoryName;
        }

        public ParamJCTable(CropDlg parentDlg, String categoryName) {
            this();
            c_categoryName = categoryName;
            this.parentDlg = parentDlg;
        }

        public int YtoRow2(int row) {
            return YtoRow(row);
        }

        public ParamJCTable() {
            //System.out.println("ParamJCTable : Constructor Start ");
            mVDataSource = new JCEditableVectorDataSource();
            //System.out.println("ParamJCTable : Constructor 152 ");
            setDataSource(mVDataSource);
            //System.out.println("ParamJCTable : Constructor 154 ");
            setTableLooks();
            //System.out.println("ParamJCTable : Constructor 156");

            getDataSource().addTableDataListener(new JCTableDataListener() {

                @Override
                public void dataChanged(JCTableDataEvent event) {
                    ////System.out.println("Data Changed handler");
                    if (event.getCommand() == JCTableDataEvent.CHANGE_VALUE) {
                        mDataChanged = true;
                    }
                }
            });
            addEditCellListener(this);
            addMouseMotionListener(this);

            //Create a custom CSH Manager for the table.
            ParamTableCSHManager cm = new ParamTableCSHManager(this);
            CSH.addManager(cm);

        }

        /************************************************************* neha */
        @Override
        public void focusGained(FocusEvent ev) {
            //   //System.out.println("editor Gained");
        }

        @Override
        public void focusLost(FocusEvent ev) {
            Component comp = ev.getOppositeComponent();
            //Click a button if the table loses focus to the button
            if (ev.getSource() instanceof JCTable) {
                if (comp != null && comp instanceof AbstractButton) {
                    //I don't know why, but if we don't test for the button, it clicks the save as button.
                    if (((AbstractButton) comp).getText().contains("Notes")) {
                        ((AbstractButton) comp).doClick();
                    }
                }
                //We don't want to commit unless we lose focus from a cell editor
                return;
            } else if (ev.getSource() instanceof BaseCellEditor) {
                //Don't commit combo boxes.  Their event code handles the commit
                if (comp instanceof JComboBox) {
                    return;
                } //Commit everything else
                else {
                    this.commitEdit(true);
                    //System.out.println("editor Committed");            
                }
                //If we lost focus to a button click it
                if (comp != null && comp instanceof AbstractButton) {
                    ((AbstractButton) comp).doClick();
                }
            }

        }
        String beforeEditValue = "";

        @Override
        public void mouseMoved(MouseEvent mouseEvent) {
            try {
                int row = YtoRow(mouseEvent.getY());
                String paramName = c_catParams.get(row);
                String tooltip = parentDlg.c_tooltipTable.get("CropDrill:" + paramName);
                if (tooltip != null) {
                    setToolTipText("<html>" + tooltip + "</html>");
                } else {
                    setToolTipText("");
                }
            } catch (Exception e) {
            }
        }

        @Override
        public void mouseDragged(MouseEvent mouseEvent) {
            return;
        }
        String afterEditValue = "";

        @Override
        public void beforeEditCell(JCEditCellEvent ev) {
            // //System.out.println("beforeEditCell");

            int row = ev.getRow();
            int column = ev.getColumn();
            beforeEditValue = (String) this.getDataSource().getTableDataItem(row, column);
        }

        @Override
        public void editCell(JCEditCellEvent ev) {
            //  //System.out.println("EditCell");
        }

        @Override
        public void afterEditCell(JCEditCellEvent ev) {
            // //System.out.println("afterEditCell");
            int row = ev.getRow();
            int column = ev.getColumn();
            String paramName = getParamName(row);
            afterEditValue = (String) this.getDataSource().getTableDataItem(row, column);
            if (beforeEditValue != null && afterEditValue != null) {
                //System.out.print("CropDlg : afterEditCell():Before Edit: "+beforeEditValue+"  after Edit: "+afterEditValue);
                //If there is a change in the value of the cell after the edit, then ask the user
                // if he needs to save the change - Neha
                if (!beforeEditValue.equals(afterEditValue)) {

                    dataChanged = true;

                    // Tell the other dialog I updated something.  It will tell the other tables
//                    String paramName = getParamName(row);

                    parentDlg.notfiyTablesOfChange(paramName, afterEditValue);
                    //  //System.out.println("ParamJCTable:aEC-CropDlg.dataChanged is set to TRUE");
                }
            }
            InputLimits.TableStatus check = checkDataCell(afterEditValue, paramName);
            test(check, row, paramName);

        }

        public String getParamName(int row) {

            CropMeta cropMeta = (CropMeta) MCREWConfig.getObjectMeta(XMLConstants.scrop);

            for (int i = 0; i <= row; i++) {
                String paramName = c_catParams.get(i);
                ParameterMeta paramMeta = cropMeta.getParameterMeta(paramName);
                String displayAttribute = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.sdisplayattribute);
                if ((displayAttribute != null) && (displayAttribute.equals(XMLConstants.sHidden))) {
                    row++;
                }
            }

            return c_catParams.get(row--);

        }

        /************************************************************* neha */
        /*********************************************************************** wjr */
        private void setTableLooks() {
            setColumnLabelDisplay(true);
            setRowLabelDisplay(false);
            setDoubleBuffered(true);
            setAutoScroll(JCTableEnum.AUTO_SCROLL_BOTH);

            //setFocusIndicator(JCTableEnum.FOCUS_NONE);
            //setFrozenColumns(2); 
            setFrozenRows(1); // header line

            mCellStyle = (JCCellStyle) getDefaultCellStyle();
            mCellStyle.setCellBorder(new JCCellBorder(JCTableEnum.BORDER_OUT));
            mCellStyle.setEditable(false);
            mCellStyle.setBackground(Color.lightGray);

            mUnHLimitCellStyle = (JCCellStyle) getDefaultCellStyle().clone();
            mUnHLimitCellStyle.setBackground(Color.pink);
            mUnHLimitCellStyle.setEditable(false);
            
            mUnSLimitCellStyle = (JCCellStyle) getDefaultCellStyle().clone();
            mUnSLimitCellStyle.setBackground(Color.orange);
            mUnSLimitCellStyle.setEditable(false);
            
            mValueCellStyle = (JCCellStyle) getDefaultCellStyle().clone(); // for the column showing parameter values
            mValueCellStyle.setBackground(Color.white);
            mValueCellStyle.setEditable(true);
            
            mHLimitCellStyle = (JCCellStyle) getDefaultCellStyle().clone();
            mHLimitCellStyle.setBackground(Color.magenta);
            mHLimitCellStyle.setEditable(true);
            
            mSLimitCellStyle = (JCCellStyle) getDefaultCellStyle().clone();
            mSLimitCellStyle.setBackground(Color.yellow);
            mSLimitCellStyle.setEditable(true);
            
            setCellStyle(JCTableEnum.ALLCELLS, VALUECOLUMN, mValueCellStyle);
            //set the cell editor for all the editable cells - neha
            if (se == null) {
                se = new JCStringCellEditor() {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void initialize(AWTEvent ev, JCCellInfo info, Object o) {
                        super.initialize(ev, info, o);

                        SwingUtilities.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                requestFocusInWindow();
                                selectAll();
                            }
                        });
                    }
                };
                se.addFocusListener(this);
            }
            mValueCellStyle.setCellEditor(se);

            CellStyleModel labelStyleModel = getDefaultLabelStyle();
            labelStyleModel.setFont(new Font("Dialog", Font.BOLD, 12));
            labelStyleModel.setCellBorderSides(JCTableEnum.BORDERSIDE_ALL);
            //setCellStyle(-1, JCTableEnum.ALLCELLS, headerStyleModel);

            setMinWidth(JCTableEnum.ALL, 75);	// default width
            setMinWidth(0, 270);					// make param prompt wider
            setMinWidth(1, 240);
            setMinWidth(2, 70);
            setFocusColor(Color.red);


            /* // Not sure why setting editor and renderer this way is not working
             try{	
             setCellEditor(Class.forName("javax.swing.JComboBox"), 
             Class.forName("com.klg.jclass.cell.editors.JCComboBoxCellEditor")
             );
             setCellRenderer(Class.forName("javax.swing.JComboBox"), 
             Class.forName("com.klg.jclass.cell.renderers.JCComboBoxCellRenderer")
             );
            
             }catch(ClassNotFoundException e){
             System.err.println("OperationDlg:setTableLooks()"+ "Class not found exception");
             }
             */
            mVDataSource.setColumnLabels(mHeaderRow);
            mVDataSource.setNumColumns(mHeaderRow.length);
            mVDataSource.setNumRows(0);
        }

        /**
         * Given the cell status, sorts the row into the correct list so it is
         * displayed correctly and will generate the correct tablestatus.
         * @param cellStatus
         * @param row 
         */
        private void test(InputLimits.TableStatus cellStatus, int row, String paramName)
        {
            switch(cellStatus)
                    {
                        case WARNSAVE:
                            setCellStyle(row, VALUECOLUMN, mSLimitCellStyle);
                            ParameterMeta paramMetaA = mCropMeta.getParameterMeta(paramName);
                            String displayAttributeA = paramMetaA.getGroupAttribute(c_categoryName, XMLConstants.sdisplayattribute);
                            if(displayAttributeA.equals("V")) setCellStyle(row, VALUECOLUMN, mUnHLimitCellStyle);
                            if(!outSoft.contains((Integer) row))
                            {
                                outSoft.add(row);
                                if(outHard.contains((Integer) row))
                                {
                                    int toRemove = outHard.indexOf(row);
//                                    outTab.remove(toRemove);
                                    outHard.remove(toRemove);
                                    if(outHard.isEmpty())
                                    {
                                        allowSave = InputLimits.TableStatus.WARNSAVE;
                                    }
                                }
                                if(allowSave == InputLimits.TableStatus.OKAY)
                                {
                                    allowSave = InputLimits.TableStatus.WARNSAVE;
                                }
                            }
                            break;
                        case NOSAVE:
                            setCellStyle(row, VALUECOLUMN, mHLimitCellStyle);
                            ParameterMeta paramMetaB = mCropMeta.getParameterMeta(paramName);
                            String displayAttributeB = paramMetaB.getGroupAttribute(c_categoryName, XMLConstants.sdisplayattribute);
                            if(displayAttributeB.equals("V")) setCellStyle(row, VALUECOLUMN, mUnSLimitCellStyle);
                            if(!outHard.contains((Integer) row))
                            {
                                outHard.add(row);
                                if(outSoft.contains((Integer) row))
                                {
                                    int toRemove = outSoft.indexOf(row);
                                    outSoft.remove(toRemove);
                                }
                                if(allowSave == InputLimits.TableStatus.OKAY ||
                                        allowSave == InputLimits.TableStatus.WARNSAVE)
                                {
                                    allowSave = InputLimits.TableStatus.NOSAVE;
                                }
                            }
                            break;
                        case CHOICE:
                            break;
                        default:
                            setCellStyle(row, VALUECOLUMN, mValueCellStyle);
                            ParameterMeta paramMetaC = mCropMeta.getParameterMeta(paramName);
                            String displayAttributeC = paramMetaC.getGroupAttribute(c_categoryName, XMLConstants.sdisplayattribute);
                            if(displayAttributeC.equals("V")) setCellStyle(row, VALUECOLUMN, mCellStyle);
                            if(outHard.contains((Integer) row))
                            {
                                int toRemove = outHard.indexOf(row);
//                                outTab.remove(toRemove);
                                outHard.remove(toRemove);
                            }
                            if(outSoft.contains((Integer) row)) 
                            {
                                int toRemove = outSoft.indexOf(row);
                                outSoft.remove(toRemove);
                            }
                            if(outHard.isEmpty() && outSoft.isEmpty())
                            {
                                allowSave = InputLimits.TableStatus.OKAY;
                            }
                    }
        }
        
        /**
         * Takes an input index of the catparams list and decomposes it into the
         * corresponding row on the table.
         * @param row
         * @return 
         */
        private int decomposeRow(int row, List<String> catParams)
        {
            int output = 0;
            for(int index = 0; index < row; index ++)
            {
                ParameterMeta paramMeta = mCropMeta.getParameterMeta(catParams.get(index));
                String displayAttribute = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.sdisplayattribute);
                if(displayAttribute != null)
                {
                    if(displayAttribute.equals("H")) continue;
                }
                output ++;
            }
            return output;
        }
        
        /**
         * The initial checkData method that iterates over every row and sets
         * each table status.
         * @param numParams
         * @param catParams 
         */
        private void checkData(int numParams, List<String> catParams)
        {
            for(int index = 0; index < numParams; index ++)
            {
                
                ParameterMeta paramMeta = mCropMeta.getParameterMeta(catParams.get(index));
                String displayAttribute = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.sdisplayattribute);
                if(displayAttribute.equals("H")) continue;
                InputLimits.TableStatus cellStatus = checkDataCell(index, catParams);
                
                switch(cellStatus)
                {
                    case WARNSAVE:
                        setCellStyle(index, VALUECOLUMN, mSLimitCellStyle);
                        if(displayAttribute.equals("V")) setCellStyle(decomposeRow(index, catParams), VALUECOLUMN, mUnSLimitCellStyle);
                        if(!outSoft.contains((Integer) index))
                        {
                            outSoft.add(index);
                            if(outHard.contains((Integer) index))
                            {
                                int toRemove = outHard.indexOf(index);
//                                    outTab.remove(toRemove);
                                outHard.remove(toRemove);
                                if(outHard.isEmpty())
                                {
                                    allowSave = InputLimits.TableStatus.WARNSAVE;
                                }
                            }
                            if(allowSave == InputLimits.TableStatus.OKAY)
                            {
                                allowSave = InputLimits.TableStatus.WARNSAVE;
                            }
                        }
                        break;
                    case NOSAVE:
                        setCellStyle(index, VALUECOLUMN, mHLimitCellStyle);
                        if(displayAttribute.equals("V")) setCellStyle(decomposeRow(index, catParams), VALUECOLUMN, mUnHLimitCellStyle);
                        if(!outHard.contains((Integer) index))
                        {
                            outHard.add(index);
                            if(outSoft.contains((Integer) index))
                            {
                                int toRemove = outSoft.indexOf(index);
                                outSoft.remove(toRemove);
                            }
                            if(allowSave == InputLimits.TableStatus.OKAY ||
                                    allowSave == InputLimits.TableStatus.WARNSAVE)
                            {
                                allowSave = InputLimits.TableStatus.NOSAVE;
                            }
                        }
                        break;
                    case CHOICE:
                        break; 
                   default:
                        setCellStyle(index, VALUECOLUMN, mValueCellStyle);
                        if(displayAttribute.equals("V")) setCellStyle(decomposeRow(index, catParams), VALUECOLUMN, mCellStyle);
                        if(outHard.contains((Integer) index))
                        {
                            int toRemove = outHard.indexOf(index);
//                                outTab.remove(toRemove);
                            outHard.remove(toRemove);
                        }
                        if(outSoft.contains((Integer) index)) 
                        {
                            int toRemove = outSoft.indexOf(index);
                            outSoft.remove(toRemove);
                        }
                        if(outHard.isEmpty() && outSoft.isEmpty())
                        {
                            allowSave = InputLimits.TableStatus.OKAY;
                        }
                }
            }
        }
        
        /**
         * Returns the Status of the table
         * @return
         */
        public InputLimits.TableStatus getTotalStatus()
        {
            return allowSave;
        }
        
        /* Clears the tabel data. On clearing all cells in a JCtable, the coloumn header disppears.
         * This functions just set the number of rows to 1 i.e makes an empty row so that column labels won't disappear.
         */
        public void clear() {
            mVDataSource.clearCells();
            mVDataSource.setNumRows(0);
        }

        public void setDataTab(CropObject pCropObject, List<String> catParams) {
            c_cropObject = pCropObject;
            c_catParams = catParams;
            //Set the "allParamsHidden" attribute for this category of the CropObject 
            //to true before setting the parameters in this category - neha
            pCropObject.allParamsHidden = true;
            CropMeta cropMeta = null;
            //Vector parameterNames = mCropObject.getParameterNames();
            List<String> parameterNames = catParams;

            /* if(catParams.isEmpty()){
             //System.out.println("setDataTab : VECTOR catParams is EMPTY");
             }*/
            int numParams = parameterNames.size();
            //System.out.println("ParamJCTable:setDataTab(): Number of Params is : " + numParams );

            if (numParams == 0) {
                System.err.println("ParamterJCTable:setDataTab(): " + "Crop Object	has no parameters");
                mVDataSource.clearCells();

                return;
            }

            //ActionMeta actionMeta = ConfigData.getObjectMeta(XMLConstants.soperation).getActionMeta(mAction.getIdentity());
            cropMeta = (CropMeta) MCREWConfig.getObjectMeta(XMLConstants.scrop);

            clearSelectedCells();
            //reset all data
            mVDataSource.clearCells();
            //reset all cell styles
            setCellStyle(JCTableEnum.ALLCELLS, JCTableEnum.ALLCELLS, mCellStyle);
            setCellStyle(JCTableEnum.ALLCELLS, VALUECOLUMN, mValueCellStyle);

            int row = 0, col = 0;

            for (int i = 0; i < numParams; i++) {
                col = 0;
                String paramName = parameterNames.get(i);
                String paramValue;

                String paramPrompt = null;
                String paramType = null;
                String displayAttribute = null;
                String valueAttribute = null;
                String format = null;
                //String units[] = new String[2];
                String units = null;
                Hashtable<String, String> paramChoices = null;

                Parameter parameter = pCropObject.getParameter(paramName);
                if (parameter != null) {
                    ParameterMeta paramMeta = null;
                    paramValue = parameter.get(XMLConstants.svalue);

                    //System.out.println("CropDlg:setDataTab" + " paramname = " + paramName + ", paramvalue = "
                    //+ paramValue + " index = " + i + " XMLConstants sValue is " + XMLConstants.svalue );
                    // Col 0 = param prompt, Col 1 = param value, Col 2 = param units
                    if (cropMeta != null) {
                        paramMeta = cropMeta.getParameterMeta(paramName);
                        if (paramMeta != null) {
                            paramPrompt = paramMeta.getPrompt();
                            paramType = paramMeta.getType();

                            units = paramMeta.getUnit(MCREWConfig.getDisplayUnit());
                            if (units == null) {
                                units = paramMeta.getUnit(XMLConstants.kPrimaryUnit);
                            }
                            displayAttribute = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.sdisplayattribute);

                            //valueAttribute = paramMeta.getAttribute(XMLConstants.svalueattribute);
                            valueAttribute = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.svalueattribute);
                            format = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.sformat);

                            paramChoices = paramMeta.getChoices();
                        }//end of if(paramMeta != null)
                        //else
                        //System.out.println("CropDlg:setDataTab:" + " Theres no parameter meta for parameter " + paramName);
                    }//end of if(cropMeta != null)

                    if (displayAttribute == null) /* For some reason, the attribute is not specifed in the file */ {
                        System.err.println("CropDlg:setDataTab(): " + "Theres no display attribute for parameter "
                                + paramName + " in the crop_lang.xml file");
                        displayAttribute = XMLConstants.sViewable;
                        //atleast one parameter has a display attribute that is NOT hidden - neha
                        pCropObject.allParamsHidden = false;
                    } else if (displayAttribute.equals(XMLConstants.sEditable)) {
                        //atleast one parameter has a display attribute that is NOT hidden - neha
                        pCropObject.allParamsHidden = false;
                    } else if (displayAttribute.equals(XMLConstants.sViewable)) {
                        //atleast one parameter has a display attribute that is NOT hidden - neha
                        pCropObject.allParamsHidden = false;
                    } else if (displayAttribute.equals(XMLConstants.sHidden)) {
                        continue; /* Hidden parameters should not be displayed on the table */

                    } //end of if-else on displayAttribute

                    if (valueAttribute == null) {
                        System.err.println("CropDlg:setDataTab(): " + "Theres no value attribute for parameter "
                                + paramName + " in the crop_lang.xml file");
                        valueAttribute = XMLConstants.sint;
                    }//end of if(valueAttribute == null)

                    if ((paramPrompt == null) || (paramPrompt.length() == 0)) {
                        paramPrompt = paramName;
                    }//end of if on paramPrompt
                    
                    mVDataSource.setTableDataItem(paramPrompt, row, col++);


                    /* If the parameter is choice list type, then instead of the actual value, 
                     * the various choices should go into the table.
                     */
                    //JComboBox choiceBox;
                    if (valueAttribute.equals(XMLConstants.schoice)) {
                        //System.out.println("choice attribute");
                        if (paramChoices == null) // due to reason such as parameter misspelled in lang file,...
                        {
                            System.err.println("OprnDlg:setDataTab(); " + paramName + " has no Choices");
                            continue;
                        }

                        Enumeration<String> enumChoices = paramChoices.elements();

                        Vector<String> choiceList = new Vector<>();
                        while (enumChoices.hasMoreElements()) {
                            String choice = enumChoices.nextElement();
                            choiceList.add(choice);
                        }
                        Collections.sort(choiceList);

                        /* XXX Temporary solution - as the above way of setting through combo box into
                         * the data source is not working
                         * In this solution, every cell has separate cell editor and cell renderer which is not a suggested way
                         * TODO: fix this
                         */
                        JCComboBoxCellEditor comboEditor = new JCComboBoxCellEditor(choiceList.toArray());
                        JCComboBoxCellRenderer comboRenderer = new JCComboBoxCellRenderer(choiceList.toArray());
                        comboEditor.setSelectedItem(paramChoices.get(paramValue));
                        comboRenderer.setSelectedItem(paramChoices.get(paramValue));

                        JCCellStyle comboStyle = (JCCellStyle) mValueCellStyle.clone();
                        comboStyle.setCellEditor(comboEditor);
                        comboStyle.setCellRenderer(comboRenderer);
                        if ((displayAttribute != null) && (displayAttribute.equals(XMLConstants.sEditable))) {
                            comboStyle.setEditable(true);
                        } else {
                            comboStyle.setEditable(false);
                            comboStyle.setBackground(MCREWConfig.getDisabledColor());
                        }

                        setCellStyle(row, col, comboStyle);

                        JComboBox<?> comboBox = (JComboBox<?>) ((comboStyle.getCellEditor()).getComponent());
                        comboBox.addItemListener(new ItemListener() {

                            @Override
                            public void itemStateChanged(ItemEvent ev) {
                                if (ev.getStateChange() == ItemEvent.SELECTED) {	////System.out.println("Item changed");
                                    commitEdit(true);
                                }
                            }
                        });

                        //Register the param with the dialog as a choice list
                        parentDlg.registerParamOnTable(paramName, mVDataSource, row, col, ParamChanger.TYPE_CHOICE);

                        //System.out.println("Table:setData()-" + "ParamChoice = " + paramChoices.get(paramValue)
                        //+ ", Value = "+ paramValue);
                        mVDataSource.setTableDataItem(paramChoices.get((paramValue)), row, col++);
                        /* END TEMPORARY SOLUTION*/

                    } else if (valueAttribute.equals(XMLConstants.smultiline)) {
                        //System.out.println("SetDataTab:MultiLine Text attribute for NOTES");
                        notes = new NotesCrop("Crop File Notes", parentDlg, this, paramValue, row, col);

                        JCCellStyle buttonStyle = (JCCellStyle) mValueCellStyle.clone();
                        buttonStyle.setCellEditor(new ButtonEditor());

                        if ((displayAttribute != null) && (displayAttribute.equals(XMLConstants.sEditable))) {
                            buttonStyle.setEditable(true);
                        }
                        buttonStyle.setBackground(MCREWConfig.getDisabledColor());
                        buttonStyle.setForeground(Color.BLACK);
                        setCellStyle(row, col, buttonStyle);

                        JButton button = (JButton) ((buttonStyle.getCellEditor()).getComponent());
                        button.setSize(60, 8);
                        button.setPreferredSize(new Dimension(60, 8));
                        // button.setBackground(Color.RED);
                        button.setOpaque(true);

                        if (displayAttribute.equals(XMLConstants.sEditable)) {
                            button.setText("Edit Notes");
                            notes.setEditable(true);
                        } else {
                            button.setText("View Notes");
                            notes.setEditable(false);
                        }

                        buttonStyle.setCellRenderer(new ButtonRenderer(button.getText()));

                        button.addActionListener(new ActionListener() {

                            @Override
                            public void actionPerformed(ActionEvent ev) {
                                //System.out.println("setDataTab():Button pressed");
                                notesButton_clicked(ev);
                            }
                        });
                        mVDataSource.setTableDataItem(paramValue, row, col++);
                        //Register the param with the dialog as text
                        parentDlg.registerParamOnTable(paramName, mVDataSource, row, col, ParamChanger.TYPE_TEXT);

                        //	mVDataSource.setTableDataItem(buttonText, row , col++);
                    } else {
                        if (displayAttribute.equals(XMLConstants.sViewable)) // Viewable attribute means not Editable
                        {
                            JCCellStyle style = (JCCellStyle) mValueCellStyle.clone();
                            style.setEditable(false);
                            style.setBackground(MCREWConfig.getDisabledColor());
                            setCellStyle(row, col, style);
                        }

                        //Set formatted renderer
                        if (format != null) {
                            JCCellStyle style = (JCCellStyle) getCellStyle(row, col);
                            setCellStyle(row, col, (JCCellStyle) style.clone());
                            getCellStyle(row, col).setCellRenderer(new MyFormattedCellRenderer(format));
                        }

                        // convert the value to alternate unit before displaying	
                        if ((MCREWConfig.getDisplayUnit() == XMLConstants.kAlternateUnit) && (paramMeta != null)) {
                            paramValue = paramMeta.convertToAlternateUnits(paramValue);

                        }
                        //Register the param with the dialog
                        parentDlg.registerParamOnTable(paramName, mVDataSource, row, col, ParamChanger.TYPE_NORMAL);

                        mVDataSource.setTableDataItem(paramValue, row, col++);
                        ////System.out.println("Opr'nDlg:setData"+ "Setting data to Non choice variable");

                    }//end of if-else if-else on valueAttribute

                    mVDataSource.setTableDataItem(units, row, col++);
                    //	mVDataSource.setTableDataItem(primaryUnit, row , col++);

                    row++;
                }//end of if(parameter != null)
            }//end of for loop

            mVDataSource.setNumRows(row);
            checkData(numParams, catParams);
        }//end of method setDataTab

        public void notesButton_clicked(java.awt.event.ActionEvent evt) {
            int row = getCurrentRow();
            int col = getCurrentColumn();
            String text = (String) getDataSource().getTableDataItem(row, col);
            notes.setText(text);
            if (notes.notesPresent == false) {
                notes.setVisible(true);
                notes.notesPresent = true;
            } else if (notes.isActive() == false) {
                notes.toFront();
                notes.setVisible(true);
                notes.requestFocus();
            }//end of else
        }

        public void setData(CropObject pCropObject) {

            CropMeta cropMeta = null;

            Vector<String> parameterNames = pCropObject.getParameterNames();
            if (parameterNames == null) {
                //System.out.println("No crop object.");
                return;
            }
            int numParams = parameterNames.size();

            if (numParams == 0) {
                System.err.println("ParamterJCTabel:setData(): " + "Crop Object	has no parameters");
                mVDataSource.clearCells();
                return;
            }

            //ActionMeta actionMeta = ConfigData.getObjectMeta(XMLConstants.soperation).getActionMeta(mAction.getIdentity());
            cropMeta = (CropMeta) MCREWConfig.getObjectMeta(XMLConstants.scrop);

            clearSelectedCells();
            //reset all data
            mVDataSource.clearCells();
            //reset all cell styles
            setCellStyle(JCTableEnum.ALLCELLS, JCTableEnum.ALLCELLS, mCellStyle);
            setCellStyle(JCTableEnum.ALLCELLS, VALUECOLUMN, mValueCellStyle);

            int row = 0, col = 0;

            for (int i = 0; i < numParams; i++) {
                col = 0;
                String paramName = parameterNames.get(i);

                String paramValue;

                String paramPrompt = null;
                String paramType = null;
                String displayAttribute = null;
                String valueAttribute = null;
                //String units[] = new String[2];
                String units = null;
                Hashtable<String, String> paramChoices = null;

                Parameter parameter = pCropObject.getParameter(paramName);
                ParameterMeta paramMeta = null;
                //paramName = parameter.get(XMLConstants.sname);
                paramValue = parameter.get(XMLConstants.svalue);

                //System.out.println("CropDlg:setData" + " paramname = " + paramName + ", paramvalue = "
                //+ paramValue + " index = " + i);
                // Col 0 = param prompt, Col 1 = param value, Col 2 = param units
                if (cropMeta != null) {
                    paramMeta = cropMeta.getParameterMeta(paramName);
                    if (paramMeta != null) {
                        paramPrompt = paramMeta.getPrompt();
                        paramType = paramMeta.getType();

                        units = paramMeta.getUnit(MCREWConfig.getDisplayUnit());
                        if (units == null) {
                            units = paramMeta.getUnit(XMLConstants.kPrimaryUnit);
                            /*
                             units[XMLConstants.kPrimaryUnit] = paramMeta.getUnit(XMLConstants.kPrimaryUnit);
                             units[XMLConstants.kAlternateUnit] = paramMeta.getUnit(XMLConstants.kAlternateUnit);
                             if(units[XMLConstants.kAlternateUnit] == null) //if the alternate unit is not present in any file 
                             units[XMLConstants.kAlternateUnit]  = units[XMLConstants.kPrimaryUnit] ;
                             */
                        }
                        displayAttribute = paramMeta.getAttribute(XMLConstants.sdisplayattribute);
                        valueAttribute = paramMeta.getAttribute(XMLConstants.svalueattribute);
                        //displayAttribute = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.sdisplayattribute);
                        //valueAttribute = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.svalueattribute);

                        paramChoices = paramMeta.getChoices();
                    } else {
                        //System.out.println("CropDlg:setData:" + " Theres no parameter meta for parameter " + paramName);
                    }
                }//end of if(cropMeta != null)

                if (displayAttribute == null) /* For some reason, the attribute is not specifed in the file */ {
                    System.err.println("CropDlg:setData(): " + "Theres no display attribute for parameter "
                            + paramName + " in the crop_lang.xml file");
                    displayAttribute = XMLConstants.sViewable;
                } else if (displayAttribute.equals(XMLConstants.sHidden)) {
                    numParams --;
                    parameterNames.remove(i);
                    i--;
                    continue; /* Hidden parameters should not be displayed on the table */

                }//end of if-else on displayAttribute

                if (valueAttribute == null) {
                    System.err.println("CropDlg:setData(): " + "Theres no value attribute for parameter "
                            + paramName + " in the crop_lang.xml file");
                    valueAttribute = XMLConstants.sint;
                }//end of if (valueAttribute != null)

                if ((paramPrompt == null) || (paramPrompt.length() == 0)) {
                    paramPrompt = paramName;
                } //end of if on paramPrompt
                
                mVDataSource.setTableDataItem(paramPrompt, row, col++);
                /* If the parameter is choice list type, then instead of the actual value, 
                 * the various choices should go into the table.
                 */
                //JComboBox choiceBox;
                if (valueAttribute.equals(XMLConstants.schoice)) //(paramType.equals(XMLConstants.schoice)) )
                {
                    //System.out.println("choice attribute");
                    if (paramChoices == null) // due to reason such as parameter misspelled in lang file,...
                    {
                        System.err.println("OprnDlg:setData(); " + paramName + " has no Choices");
                        continue;
                    }

                    Enumeration<String> enumChoices = paramChoices.elements();

                    Vector<String> choiceList = new Vector<>();
                    while (enumChoices.hasMoreElements()) {
                        String choice = enumChoices.nextElement();
                        choiceList.add(choice);
                    }
                    Collections.sort(choiceList);

                    /* XXX - Not sure why this method of setting the combobox into the data source is NOT working*/
                    /*
                     choiceBox = new JComboBox(choiceList);
                     choiceBox.setSelectedItem(paramChoices.get(paramValue));
                     mVDataSource.setTableDataItem(choiceBox, row, col++);
                     //mVDataSource.setTableDataItem("HaHaHa", row, col++);
                     //System.out.println("Opr'nDlg:setData"+ "Setting data to comboBox");
                     */

                    /* XXX Temporary solution - as the above way of setting through combo box into the data source is not working
                     * In this solution, every cell has separate cell editor and cell renderer which is not a suggested way
                     */
                    JCComboBoxCellEditor comboEditor = new JCComboBoxCellEditor(choiceList.toArray());
                    JCComboBoxCellRenderer comboRenderer = new JCComboBoxCellRenderer(choiceList.toArray());
                    comboEditor.setSelectedItem(paramChoices.get(paramValue));
                    comboRenderer.setSelectedItem(paramChoices.get(paramValue));

                    JCCellStyle comboStyle = (JCCellStyle) mValueCellStyle.clone();
                    comboStyle.setCellEditor(comboEditor);
                    comboStyle.setCellRenderer(comboRenderer);
                    if ((displayAttribute != null) && (displayAttribute.equals(XMLConstants.sEditable))) {
                        comboStyle.setEditable(true);
                    }
                    setCellStyle(row, col, comboStyle);

                    JComboBox<?> comboBox = (JComboBox<?>) ((comboStyle.getCellEditor()).getComponent());
                    comboBox.addItemListener(new ItemListener() {

                        @Override
                        public void itemStateChanged(ItemEvent ev) {
                            if (ev.getStateChange() == ItemEvent.SELECTED) {	////System.out.println("Item changed");
                                commitEdit(true);
                            }
                        }
                    });
                    //System.out.println("Table:setData()-" + "ParamChoice = " + paramChoices.get(paramValue)
                    //+ ", Value = "+ paramValue);
                    mVDataSource.setTableDataItem(paramChoices.get((paramValue)), row, col++);
                    /* END TEMPORARY SOLUTION*/

                } else if (valueAttribute.equals(XMLConstants.smultiline)) {
                    //System.out.println("SetData:MultiLine Text attribute for NOTES");
                    JCCellStyle buttonStyle = (JCCellStyle) mValueCellStyle.clone();
                    buttonStyle.setCellEditor(new ButtonEditor());

                    if ((displayAttribute != null) && (displayAttribute.equals(XMLConstants.sEditable))) {
                        buttonStyle.setEditable(true);
                    }
                    buttonStyle.setBackground(MCREWConfig.getDisabledColor());
                    buttonStyle.setForeground(Color.BLACK);
                    setCellStyle(row, col, buttonStyle);

                    JButton button = (JButton) ((buttonStyle.getCellEditor()).getComponent());
                    button.setSize(60, 8);
                    button.setPreferredSize(new Dimension(60, 8));
                    button.setOpaque(true);
                    button.setText("Notes");

                    buttonStyle.setCellRenderer(new ButtonRenderer(button.getText()));
                    button.addActionListener(new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent ev) {
                            //System.out.println("setDataTab():Button pressed");
                        }
                    });

                    //	mVDataSource.setTableDataItem(buttonText, row , col++);
                } else {
                    if (displayAttribute.equals(XMLConstants.sViewable)) // Viewable attribute means not Editable
                    {
                        JCCellStyle style = (JCCellStyle) mValueCellStyle.clone();
                        style.setEditable(false);
                        style.setBackground(MCREWConfig.getDisabledColor());
                        setCellStyle(row, col, style);
                    }
                    // convert the value to alternate unit before displaying	
                    if ((MCREWConfig.getDisplayUnit() == XMLConstants.kAlternateUnit) && (paramMeta != null)) {
                        paramValue = paramMeta.convertToAlternateUnits(paramValue);
                    }
                    mVDataSource.setTableDataItem(paramValue, row, col++);
                    ////System.out.println("Opr'nDlg:setData"+ "Setting data to Non choice variable");
                }//end of if-else-if-else on valueAttribute

                mVDataSource.setTableDataItem(units, row, col++);
                //	mVDataSource.setTableDataItem(primaryUnit, row , col++);		
                row++;

            }//end of for loop

            /*
             if(numRows > 0)
             mVDataSource.setNumRows(numRows);
             else
             mVDataSource.setNumRows(1); //show atleast 1 row, else the headers disappear
             */
            mVDataSource.setNumRows(row);

        }


        /* Saves the new values from the dataSource into the Action (mAction) object
         *
         */
        public void saveDataSource(CropObject pCropObject) {
            /* When the table data is commited, only the data in mVDataSource is saved. The data in the mCropObject object
             * isn't modified. This function saves the data into mCropObhecjt. Note that, mCropObject points to the same 
             * parameter objects as that of in the operation holding this crop. See getCrop() in OperationObject for more details
             * If a data values is being displayed and edited in alternate units,
             * then the value has to be converted to primary units 
             * before being saved.
             */
            if (pCropObject == null) {
                return; // Theres no data in the table
            }
            if (mDataChanged == false) // nothing to save
            {
                return;
            }
            dataChanged = true;
            //  //System.out.println("ParamJCTable:sDs-CropDlg.dataChanged is set to TRUE");

            mDataChanged = false; //reset the boolean varaible

            CropMeta cropMeta = null;
            Vector<String> parameterNames = pCropObject.getParameterNames();
            int numParams = parameterNames.size();
            ////System.out.println("CropDlg : SaveDataSource : Parameter Names :--" + numParams);

            int row = 0; /* Note that row is != numParams as some prameter might be hidden */

            //ActionMeta actionMeta = ConfigData.getObjectMeta(XMLConstants.soperation).getActionMeta(mAction.getIdentity());
            cropMeta = (CropMeta) MCREWConfig.getObjectMeta(XMLConstants.scrop);

            // The table displays all the parameters from the this Action in the order obtained through the hashtable 
            // in setData()
            for (int i = 0; i < numParams; i++) {
                Parameter parameter = null;
                ParameterMeta paramMeta = null;

                String paramName = parameterNames.get(i);
                ////System.out.println("CropDlg : SaveDataSource : Parameter Name is :--" + paramName);
                //String paramType = null;
                //String primaryUnit = null;
                String displayAttribute = null;
                String valueAttribute = null;
                Hashtable<String, String> paramChoices = null;

                parameter = pCropObject.getParameter(paramName);
                if (parameter == null) {
                    System.err.println("CropDlg:saveDatasource(): " + "Theres no parameter value for parameter " + paramName);
                    continue;
                }

                // //System.out.println("saveDataSource" + ", index = " + row + ", paramName: ," + paramName );
                if (cropMeta != null) {
                    // paramType = actionMeta.getParamType(paramName);
                    // primaryUnit = actionMeta.getParamUnit(paramName, XMLConstants.kPrimaryUnit);
                    paramMeta = cropMeta.getParameterMeta(paramName);
                    if (paramMeta != null) {
                        displayAttribute = paramMeta.getAttribute(XMLConstants.sdisplayattribute);
                        valueAttribute = paramMeta.getAttribute(XMLConstants.svalueattribute);
                        paramChoices = paramMeta.getChoices(); // actionMeta.getParamChoices(paramName);
                        //System.out.println( " CropDlg:saveDatasource: Dispaly Attribute :-" + displayAttribute
                        //+ "Value Attribute :-" + valueAttribute );
                    }
                    //else
                    //System.out.println("CropDlg:saveDatasource:" + " Theres no parameter meta for parameter " + paramName);

                }

                if ((displayAttribute != null) && (displayAttribute.equals(XMLConstants.sHidden))) {
                    continue; // Hidden parameters are not be displayed on the table
                    //If Value attribute is multiline, it indicates Notes which is 
                    //being saved separately - neha
                }
                if (valueAttribute != null && valueAttribute.equals(XMLConstants.smultiline)) {
                    continue;
                }
                String oldValue = parameter.get(XMLConstants.svalue);
                String newValue = mVDataSource.getTableDataItem(row, VALUECOLUMN).toString();
                row++;

                //System.out.println("Row index = " + row + "Column index = " + VALUECOLUMN + " New value = "
                //+ newValue + " Old value = " + oldValue);
                if (newValue == null) {
                    //System.out.println("CropDlg:saveDataSource " + "Param '" + paramName + "' is null");
                    continue;
                }
                //String displayUnit = (String)mVDataSource.getTableDataItem(row, UNITSCOLUMN);
                // the units in which parameters are displayed

                /* choice list needs to be handled specially as the choices (strings) are displayed in the table whereas the 
                 * choice values (integers) are saved.
                 */
                if (valueAttribute != null && valueAttribute.equals(XMLConstants.schoice)) {
                    //System.out.println("choice param value = "  + newValue);

                    if (paramChoices == null) // due to reasons such as parameter misspelled in lang file,...
                    {
                        System.err.println("OprnDlg:setData(); " + paramName + " has no Choices");
                        continue;
                    }

                    //get the key corresponding to the choice displayed
                    Enumeration<String> keys = paramChoices.keys();
                    while (keys.hasMoreElements()) {
                        String keyVal = keys.nextElement();
                        String toCompare = paramChoices.get(keyVal);
                        if (toCompare.equals(newValue)) {
                            parameter.setValue(keyVal);
                            ////System.out.println("Hashtable Values are = "  + toCompare);
                            break;
                        }
                    }
                } // end if 
                else //all other types
                {
                    String valueToSet = newValue;

                    if (MCREWConfig.getDisplayUnit() != XMLConstants.kPrimaryUnit) // Conversions needed
                    {
                        if (paramMeta != null) {
                            valueToSet = paramMeta.convertToPrimaryUnits(newValue);
                            //System.out.println("CropDlg:saveDataSource() :
                            //Converted new value " + newValue + " to " + valueToSet);
                        }
                    }

                    if (!(oldValue.equals(valueToSet))) {
                        /* Values should be written out in proper type i,e if user types in 5.00 for an integer value, 
                         * then it should be converted to 5 before putting the into the parameter
                         */
                        String properTypeValue = valueToSet;
                        if (paramMeta != null) {
                            properTypeValue = paramMeta.convertToProperType(properTypeValue);
                        }
                        parameter.setValue(properTypeValue);
                    }
                } // else all other types

            } // end of for
        }

        public void saveTabDataSource(CropObject pCropObject, Vector<String> param) {
            /* When the table data is commited, only the data in mVDataSource is saved. The data in the mCropObject object
             * isn't modified. This function saves the data into mCropObject. Note that, mCropObject points to the same 
             * parameter objects as that of in the operation holding this crop. See getCrop() in OperationObject for more details
             * If a data values is being displayed and edited in alternate units,
             * then the value has to be converted to primary units 
             * before being saved.
             */
            if (param.isEmpty()) {
                //System.out.println("saveTabDataSource : VECTOR param is EMPTY");
                return;
            }

            if (pCropObject == null) {
                return; // Theres no data in the table
            }

            if (mDataChanged == false) { // nothing to save
                return;
            }

            dataChanged = true;

            //  //System.out.println("ParamJCTable:sTDS-CropDlg.dataChanged is set to TRUE");
            mDataChanged = false; //reset the boolean varaible

            CropMeta cropMeta = null;
            //Vector parameterNames = mCropObject.getParameterNames();
            Vector<String> parameterNames = param;

            int numParams = parameterNames.size();
            //System.out.println("CropDlg : saveTabDataSource() : # Parameter Names : " + numParams);

            int row = 0; /* Note that row is != numParams as some prameter might be hidden */

            //ActionMeta actionMeta = ConfigData.getObjectMeta(XMLConstants.soperation).getActionMeta(mAction.getIdentity());
            cropMeta = (CropMeta) MCREWConfig.getObjectMeta(XMLConstants.scrop);

            // The table displays all the parameters from the this Action in the order obtained through the hashtable 
            // in setData()
            for (int i = 0; i < numParams; i++) {
                Parameter parameter = null;
                ParameterMeta paramMeta = null;

                String paramName = parameterNames.get(i);
                String displayAttribute = null;
                String valueAttribute = null;
                Hashtable<String, String> paramChoices = null;

                parameter = pCropObject.getParameter(paramName);

                if (parameter == null) {
                    System.err.println("CropDlg:saveTabDataSource(): Theres no parameter value for parameter " + paramName);
                    continue;
                }

                // //System.out.println("saveDataSource" + ", index = " + row + ", paramName: ," + paramName );
                if (cropMeta != null) {
                    // paramType = actionMeta.getParamType(paramName);
                    // primaryUnit = actionMeta.getParamUnit(paramName, XMLConstants.kPrimaryUnit);
                    paramMeta = cropMeta.getParameterMeta(paramName);
                    if (paramMeta != null) {
                        displayAttribute = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.sdisplayattribute);
                        valueAttribute = paramMeta.getGroupAttribute(c_categoryName, XMLConstants.svalueattribute);
                        paramChoices = paramMeta.getChoices();
                        //displayAttribute = paramMeta.getAttribute(XMLConstants.sdisplayattribute);
                        // actionMeta.getParamAttribute(paramName, XMLConstants.sdisplayattribute);
                        //valueAttribute = paramMeta.getAttribute(XMLConstants.svalueattribute);
                        //actionMeta.getParamAttribute(paramName, XMLConstants.svalueattribute);
                        //System.out.println( " CropDlg : saveTabDataSource() : Dispaly Attribute : "
                        //+ displayAttribute + " Value Attribute : " + valueAttribute );
                    }
                    //else
                    //System.out.println("CropDlg : saveTabDataSource() : " + " Theres no parameter meta for parameter "
                    //+ paramName);

                }

                if ((displayAttribute != null) && (displayAttribute.equals(XMLConstants.sHidden))) {
                    continue; // Hidden parameters are not be displayed on the table
                }

                String oldValue = parameter.get(XMLConstants.svalue);
                String newValue = (String) mVDataSource.getTableDataItem(row, VALUECOLUMN);
                row++;

                //System.out.println("Row index = " + row + "Column index = " + VALUECOLUMN
                //+ " New value = " + newValue + " Old value = " + oldValue);
                if (newValue == null) {
                    //System.out.println("CropDlg : saveTabDataSource() : Param '" + paramName + "' is null");
                    continue;
                }
                //String displayUnit = (String)mVDataSource.getTableDataItem(row, UNITSCOLUMN);
                // the units in which parameters are displayed

                /* choice list needs to be handled specially as the choices (strings) are displayed in the table whereas the 
                 * choice values (integers) are saved.
                 */
                if ((valueAttribute != null) && (valueAttribute.equals(XMLConstants.schoice))) {
                    ////System.out.println("choice param value = "  + newValue);

                    if (paramChoices == null) // due to reasons such as parameter misspelled in lang file,...
                    {
                        System.err.println("CropDlg : saveTabDataSource() " + paramName + " has no Choices");
                        continue;
                    }

                    //get the key corresponding to the choice displayed
                    Enumeration<String> keys = paramChoices.keys();
                    while (keys.hasMoreElements()) {
                        String keyVal = keys.nextElement();
                        String toCompare = paramChoices.get(keyVal);
                        if (toCompare.equals(newValue)) {
                            parameter.setValue(keyVal);
                            //System.out.println("Hashtable Values are = "  + toCompare);
                            break;
                        }
                    }
                } // end if 
                else //all other types
                {
                    String valueToSet = newValue;

                    if (MCREWConfig.getDisplayUnit() != XMLConstants.kPrimaryUnit) // Conversions needed
                    {
                        if (paramMeta != null) {
                            valueToSet = paramMeta.convertToPrimaryUnits(newValue);
                            //System.out.println("CropDlg:saveTabDataSource() :
                            //Converted new value " + newValue + " to " + valueToSet);
                        }
                    }

                    if (!(oldValue.equals(valueToSet))) {
                        /* Values should be written out in proper type i,e if user types in 5.00 for an integer value, 
                         * then it should be converted to 5 before putting the into the parameter
                         */
                        String properTypeValue = valueToSet;
                        if (paramMeta != null) {
                            properTypeValue = paramMeta.convertToProperType(properTypeValue);
                        }
                        parameter.setValue(properTypeValue);
                    }
                } // else all other types

            } // end of for
        }
    }

    /**
     *
     */
    public static class ButtonRenderer extends JButton implements JCComponentCellRenderer {

        private static final long serialVersionUID = 1L;

        /**
         *
         * @param text
         */
        public ButtonRenderer(String text) {
            super();
            setText(text);
        }

        @Override
        public Component getRendererComponent(JCCellInfo cellinfo, Object o, boolean selected) {
            return this;
        }
    }

    /**
     *
     */
    public static class ButtonEditor extends JButton implements JCCellEditor {

        private static final long serialVersionUID = 1L;

        /**
         *
         */
        protected JCCellEditorSupport support = new JCCellEditorSupport();

        /**
         *
         */
        protected JCCellInfo cellInfo;

        /**
         *
         */
        public ButtonEditor() {
            this(null);
        }

        /**
         *
         * @param text
         */
        public ButtonEditor(String text) {
            super(text);
        }

        @Override
        public void initialize(AWTEvent ev, JCCellInfo info, Object o) {
        }

        @Override
        public boolean stopCellEditing() {
            return true;
        }

        @Override
        public void cancelCellEditing() {
            repaint();
        }

        @Override
        public boolean isModified() {
            return false;
        }

        @Override
        public Component getComponent() {
            return this;
        }

        @Override
        public Object getCellEditorValue() {
            return this;
        }

        /**
         *
         */
        protected JCKeyModifier[] keys = null;

        @Override
        public JCKeyModifier[] getReservedKeys() {
            return keys != null ? Arrays.copyOf(keys, keys.length) : null;
        }

        @Override
        public void addCellEditorListener(JCCellEditorListener l) {
            support.addCellEditorListener(l);
        }

        @Override
        public void removeCellEditorListener(JCCellEditorListener l) {
            support.removeCellEditorListener(l);
        }
    }

    static class NotesCrop extends usda.weru.mcrew.gui.NotesMan_n {

        private static final long serialVersionUID = 1L;

        public String title;
        public final int WIDTH = 500;
        public final int HEIGHT = 300;
        //This tells us if the Notes frame is presently instantiated.
        public boolean notesPresent = false;
        public ParamJCTable tableRef;
        private final int row;
        private final int col;
        private String paramValue = "";

        /** Creates a new instance of NotesCrop */
        public NotesCrop(String t, java.awt.Dialog parent, Component tableParent, String paramValue, int row, int col) {
            super(parent, true);
            setTitle(t);
            tableRef = (ParamJCTable) tableParent;
            this.paramValue = paramValue;
            this.row = row;
            this.col = col;
            JTA_Notes.setText(paramValue);
            tableRef.parentDlg.notesDataChanged = false;
        }

        @Override
        public void JBSave_actionPerformed(java.awt.event.ActionEvent evt) {
            paramValue = JTA_Notes.getText();
            //   //System.out.println("NotesCrop:JBSave_actionPerformed:newValue:"+paramValue);
            //tableRef.mVDataSource.setTableDataItem(paramValue, row , tableRef.VALUECOLUMN);
            tableRef.mVDataSource.setTableDataItem(paramValue, row, col);
            tableRef.mDataChanged = true;
            tableRef.parentDlg.dataChanged = true;
            //   //System.out.println("NotesCrop:-JBS_aP:cropDlg.dataChanged is set to TRUE");
            tableRef.parentDlg.notesDataChanged = true;
            notesPresent = false;

            this.dispose();
        }

        @Override
        public void JBCancel_actionPerformed(java.awt.event.ActionEvent evt) {
            notesPresent = false;
            tableRef.parentDlg.notesDataChanged = false;
            this.dispose();
        }

        public void setText(String text) {
            JTA_Notes.setText(text);
        }

        public void setEditable(boolean editable) {
            JB_Save.setVisible(editable);
            JTA_Notes.setEditable(editable);
            JB_Cancel.setText(editable ? "Cancel" : "Close");
        }
    }

    static class ParamChanger {

        JCEditableVectorDataSource c_dataSource;
        final static int TYPE_NORMAL = 1;
        final static int TYPE_CHOICE = 2;
        final static int TYPE_TEXT = 3;
        int c_row;
        int c_col;
        int c_type;

        ParamChanger(JCEditableVectorDataSource dataSource, int row, int col, int type) {
            c_dataSource = dataSource;
            c_row = row;
            c_col = col;
            c_type = type;
        }

        public void updateValue(Object newValue) {
            switch (c_type) {
                case TYPE_NORMAL:
                    c_dataSource.setTableDataItem(newValue, c_row, c_col);
                    break;
                case TYPE_CHOICE:
                    c_dataSource.setTableDataItem(newValue, c_row, c_col);
                    break;
                case TYPE_TEXT:
                    //Text is not supported yet
                    break;
            }
        }
    }
}
