/* Title:		OperationDlg.java
 * Version	
 * Author		Sada
 * Company: USDA-ARS
 * Date:    July, 2003
 * Description: OperationDlg screen displays the values of all parameters of the selected operation.
 * Paramter values can also be modified from here. Also, modified values can be saved as a new operation.
 * 
 */
package usda.weru.mcrew;

import com.klg.jclass.cell.JCCellInfo;
import com.klg.jclass.cell.editors.BaseCellEditor;
import com.klg.jclass.cell.editors.JCComboBoxCellEditor;
import com.klg.jclass.cell.editors.JCStringCellEditor;
import com.klg.jclass.cell.renderers.JCComboBoxCellRenderer;
import com.klg.jclass.table.CellStyleModel;
import com.klg.jclass.table.JCCellBorder;
import com.klg.jclass.table.JCCellStyle;
import com.klg.jclass.table.JCEditCellEvent;
import com.klg.jclass.table.JCEditCellListener;
import com.klg.jclass.table.JCTable;
import com.klg.jclass.table.JCTableDataEvent;
import com.klg.jclass.table.JCTableDataListener;
import com.klg.jclass.table.JCTableEnum;
import com.klg.jclass.table.data.JCEditableVectorDataSource;

import de.schlichtherle.truezip.file.TFile;

import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.help.CSH;
import javax.help.HelpBroker;
import javax.help.HelpSet;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import usda.weru.util.ConfigData;

import usda.weru.util.Help;
import usda.weru.util.Util;
import usda.weru.util.wepsFileChooser2.WepsFileChooser2;
import usda.weru.util.wepsFileChooser2.WepsFileTypes2;
import usda.weru.weps.fuel.FuelChooser;

/**
 * OperationDlg screen displays the values of all parameters of the selected operation.
 * Parameter values can also be modified from here. Also, modified values can be saved as
 * a new operation.
 */
public class OperationDlg extends usda.weru.mcrew.gui.OperationDlg_n {

    private static final long serialVersionUID = 1L;

    static final int MIN_WIDTH = 820;
    static final int MIN_HEIGHT = 600;
    int sideOffset = 10;
    int componentOffSet = 5;
    Hashtable<String, String> c_tooltipTable;
    private JList<Identity> mProcessGroupList;
    private ArrayList<Identity> outTab;
    myListModel<Identity> mIdListModel; // even though (presently) only action names are put in the JList, the corresponding 
    // identities are stored in mIdListModel for faster access to the appropriate actions.
    List<Action> mActions;
    int mSelectedIndex, mAdditionalIndex, listOffsetIndex;
    Identity mSelectedIdentity, mAdditionalIdentity;
    OperationObject mOprnObj; // holds a copy (clone) of Operation Object passed to the constructor4
    private OperationMeta mOprnMeta;
    OperationObject mOriginalOprnObj; // Holds the operation object passed. This is updated only if user clicks OK.
    OperationObject mSaveOprnObj;
    String mOperationActionName;
    ActionJCTable mOperationTable, mMiddleTable, mLowerTable;
    ActionJCTable mOperationTable2, mMiddleTable2, mLowerTable2;
    /**
     * Variables to store whether the Drill down can save, and offending cells
     */
    private InputLimits.TableStatus allowSave = InputLimits.TableStatus.OKAY;
    ArrayList<Integer> outHard = new ArrayList<>();
    ArrayList<Integer> outSoft = new ArrayList<>();
    //An array list of parameter names corresponding to outTab, for stacking outlimits.
    ArrayList<String> outTabName = new ArrayList<>();
    
    private Table origin; //This is just so we can activate checkData upon exit.
    
    /**
     * This is the default group that is selected when the operation dialog screen appears.
     */
    public static final int kDefaultSelection = 0;
    /**
     * String that separates the process or group Id from the actual value that is 
     * visible in the text area of the operation dialog.
     */
    public static final String sIdNameSeparator = ":";
    /**
     * String that indicates if there are no actions available.
     */
    public static final String sNoAction = "No Action";
    /**
     * String that shows the parameters that are associated with a group.
     */
    public static final String sGroupParameters = "Groups Parameters  ";
    /**
     * String that shows the parameters that are associated with a process.
     */
    public static final String sProcessParameters = "Process Parameters  ";
    /**
     * The parameters that are used for selecting the objects to be viewed in bottom 
     * panel i:e the process panel
     */
    public static final String sSelectionParameters = "Selection Parameters  ";
    /**
     * Indicates whether the data in any of the three tables of operation panels
     * has been changed. Set to true if changed else false.
     */
    protected boolean dataChanged = false;
    /**
     * Flag that indicates if the data in the notes of the Operation Drill Down Screen was
     * changed which helps in saving the values in the underlying datastructure - neha
     */
    protected boolean notesDataChanged = false;
    ManageData c_manage;
    RowInfo c_row;

    /**
     * Three argument constructor that needs the pointer to a frame in which it is
     * to be displayed, the operation object that hold the operation data together,
     * and the date string.
     * @param tab: table origin.
     *      also derives the frame object in which the GUI is displayed.
     * @param pOprnObj The operation object that holds all the information to be
     * displayed in the operation dialog GUI.
     * @param pDate The date string to be set for the datefield.
     * @param manage
     * @param row
     */
    public OperationDlg(Table tab, OperationObject pOprnObj, String pDate, ManageData manage, RowInfo row) {
        super(Util.getParentJFrame(tab));
        origin = tab;
        outTab = new ArrayList<Identity>();
        c_manage = manage;
        c_row = row;
        
        if(pOprnObj.hasCrop() && pOprnObj.getCropName().equals("Select a Crop")){
            fallthroo = true;
        }
        
        mOriginalOprnObj = pOprnObj;
        mOprnObj = (OperationObject) mOriginalOprnObj.clone();

        mIdListModel = new myListModel<Identity>();
        JTF_operationName.setText(pOprnObj.getOperationName());
        JTF_date.setText(pDate);

        mOperationTable = new ActionJCTable(this);
        mMiddleTable = new ActionJCTable(this);
        mLowerTable = new ActionJCTable(this);

        dataChanged = false;
        notesDataChanged = false;

        initialize();
  
        mProcessGroupList = new JList<>(mIdListModel);
        mProcessGroupList.setSelectedIndex(kDefaultSelection);
        mSelectedIndex = kDefaultSelection;
        if (mIdListModel.get(mSelectedIndex) != null) {
            mSelectedIdentity = mIdListModel.get(mSelectedIndex); // set 0th item as default selected

            setAllSelections();
            mProcessGroupList.addMouseListener(new ListMouseAdapter());
            mProcessGroupList.setCellRenderer(new CustomCellRenderer());
//            System.out.println("here"+mProcessGroupList.getSelectedValue().id);
        }
        JSP_list.getViewport().setView(mProcessGroupList);

        JSP_upperParam.getViewport().setView(mOperationTable);
        JSP_middleParam.getViewport().setView(mMiddleTable);
        JSP_lowerParam.getViewport().setView(mLowerTable);
        
        mOperationTable2 = new ActionJCTable(this);
        mMiddleTable2 = new ActionJCTable(this);
        mLowerTable2 = new ActionJCTable(this);
        
        showTables();
        Util.loadToolTips((Container) this, new TFile("mcrew_cfg", "mcrewtooltips.cfg"));
    }
    
    /**
     * This method initializes the operation table data with the meta data that is 
     * associated with identities as keys to the respective objects e:g Action objects 
     * or data structures that hold these objects.
     */
    public void initialize() {
        int ListModelIndex = 0;

        mActions = mOprnObj.getAllActions();
        List<Identity> mActionIdVec = mOprnObj.getAllIds();

        for (int i = 0; i < mActionIdVec.size(); i++) {

            Identity identity = mActionIdVec.get(i);
            Action action = mActions.get(i);
            
            //*******"here" is where the operation dialog gets set initially, it does show p66 as an option 
            if (action.isOperation()) {
                mOperationTable.setData(action);

                mOperationActionName = identity.toString() + sIdNameSeparator + action.getActionName();
                JL_OperationAction.setText(mOperationActionName);
                listOffsetIndex++;  // Operation action not added to display list, so increment offset counter

                continue; // Theres no need to add Operation action into ProcessGroup action JList
            }

            mIdListModel.add(ListModelIndex, identity);
            ListModelIndex++;
        }

        c_tooltipTable = Util.loadToolTipsTable(new TFile("mcrew_cfg", "mcrewtooltips.cfg"));
        addHelp();
    }

    
    /**
     * This method checks the new data to be put in, indicates a change of cell
     * color if necessary.
     */
    private InputLimits.TableStatus checkDataInit(int row, List<String> catParams)
    {
        String paramName = catParams.get(row);
        for(Action token : mOprnObj.getAllActions())
        {
            try
            {
                String value = token.getValue(paramName);
                ActionMeta actionMeta = MCREWConfig.getObjectMeta(XMLConstants.soperation).getActionMeta(token.getIdentity());
                ParameterMeta limits = actionMeta.getParameterMeta(paramName);
                if(limits.getGroupAttribute(paramName, XMLConstants.svalueattribute).
                        equals(XMLConstants.schoice)) return InputLimits.TableStatus.CHOICE;
                if(limits.getGroupAttribute(paramName, XMLConstants.svalueattribute).
                        equals(XMLConstants.smultiline)) return InputLimits.TableStatus.CHOICE;
                if(token.getIdentity().equals(new Identity(51, "P")))
                {
                    //We only want to try and bound an item if it is listed under decomp parms
                    if(mOprnObj.getCrop().getParameter("idc") != null)
                    {   
                        if(mOprnObj.getCrop().getParameter("idc").getValue().equals("0") 
                                && !mOprnObj.getCrop().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) value = limits.convertToPrimaryUnits(value);
                InputLimits.TableStatus currentCellStatus = limiter.evaluateInput(value);
                setOutTab(currentCellStatus, token, paramName);
                return currentCellStatus;
            }
            catch(NullPointerException incorectAction){}
        }
        return InputLimits.TableStatus.OKAY;
    }
    
    /**
     * This method checks the new data to be placed in a cell, indicates a change of cell
     * color if necessary.
     */
    private InputLimits.TableStatus checkDataCell(String value, String paramName)
    {
        for(Action token : mOprnObj.getAllActions())
        {
            try
            {
                if(value == null) return InputLimits.TableStatus.OKAY;
                String text = value;
                ActionMeta actionMeta = MCREWConfig.getObjectMeta(XMLConstants.soperation).getActionMeta(token.getIdentity());
                ParameterMeta limits = actionMeta.getParameterMeta(paramName);
                if(limits.getGroupAttribute(paramName, XMLConstants.svalueattribute).
                        equals(XMLConstants.schoice)) return InputLimits.TableStatus.CHOICE;
                if(limits.getGroupAttribute(paramName, XMLConstants.svalueattribute).
                        equals(XMLConstants.smultiline)) return InputLimits.TableStatus.CHOICE;
                if(token.getIdentity().equals(new Identity(51, "P")))
                {
                    //We only want to try and bound an item if it is listed under decomp parms
                    if(mOprnObj.getCrop().getParameter("idc") != null)
                    {
                        if(mOprnObj.getCrop().getParameter("idc").getValue().equals("0") 
                                && !mOprnObj.getCrop().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);
                setOutTab(currentCellStatus, token, paramName);
                return currentCellStatus;
            }
            catch(NullPointerException incorectAction){}
        }
        return null;
    }
    
    /**
     * Set Tabs during initialization
     */
    private void checkTabInit()
    {
        for(Action token : mOprnObj.getAllActions())
        {
            for(String name : token.mParameterNames)
            {
                Parameter current = token.getParameter(name);
                Hashtable<String, String> between = current.mParameter;
                String value = between.get("value"); 
                ActionMeta actionMeta = MCREWConfig.getObjectMeta(XMLConstants.
                        soperation).getActionMeta(token.getIdentity());
                ParameterMeta limits = actionMeta.getParameterMeta(name);
                if (limits == null) {
                    continue;
                }
                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 check = limiter.evaluateInput(value);
                setOutTab(check, token, name);
            }
        }
    }
    
    /**
     * Sets the cell status of a tab, which indicates an action that contributes to the
     * operation.  
     */
    private void setOutTab(InputLimits.TableStatus status, Action token, String check)
    {
        Identity id = token.getIdentity();
        if(status == null) return;
        switch(status)
        {
            case WARNSAVE:
                if(outTabName.contains(check))
                {
                    outTab.remove(id);
                    outTabName.remove(check);
                }
                break;
            case NOSAVE:
                if(!outTabName.contains(check))
                {
                    outTab.add(id);
                    outTabName.add(check);
                }
                break;
            case CHOICE:
                break;
            case OKAY:
                if(outTabName.contains(check))
                {
                    outTab.remove(id);
                    outTabName.remove(check);
                }
                break;
            default:
        }
    }
    
    /**
     * Adds help, generic.
     */
    private void addHelp() {
        addCSH(Help.getHelpSet());
    } //end of addhelp()

    /**
     * Adds help based on the HelpSet Parameter inputted.
     * @param hs 
     */
    private void addCSH(HelpSet hs) {
        HelpBroker hb = hs.createHelpBroker();

        hb.enableHelpKey(getRootPane(), "operation_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(JTF_operationName, "operation_drill_operationname_html");
        CSH.setHelpIDString(operationNameLabel, "operation_drill_operationname_html");
        CSH.setHelpIDString(JP_toolbar, "operation_drill_toolbar_html");
        CSH.setHelpIDString(JP_upper, "operation_drill_operationparameters_html");
        CSH.setHelpIDString(JP_middle, "operation_drill_groupparameters_html");
        CSH.setHelpIDString(JP_lower, "operation_drill_processparameters_html");
        CSH.setHelpIDString(JTF_date, "operation_drill_date_html");
        CSH.setHelpIDString(JL_Date, "operation_drill_date_html");
        CSH.setHelpIDString(JLabel1, "operation_drill_list_html");
        CSH.setHelpIDString(JSP_list, "operation_drill_list_html");

        CSH.setHelpIDString(JB_cancel, "operation_toolbar_cancel_html");
        CSH.setHelpIDString(JB_saveAs, "operation_toolbar_save_html");
        CSH.setHelpIDString(JB_help, "operation_toolbar_help_html");
        CSH.setHelpIDString(JB_close, "operation_toolbar_return_html");

    }//end of addCSH

    /** If a process is selected, then this function finds the group to which
     * this program belongs to. It then sets both of them as selectedIndices.
     */
    public void setAllSelections() {
        int selections[] = new int[2]; //1- space for Selected and other for secondary identity index;

        mAdditionalIdentity = null;
        ActionMeta actionMeta = MCREWConfig.getObjectMeta(XMLConstants.soperation).getActionMeta(mSelectedIdentity);
        if (actionMeta == null) {
            return;
        }
        List<Identity> groupId = actionMeta.getGroupId(); // Get the groups, this proces (if it is a processs) belongs to.

        // If selected item on is not a process, then getGroupId() returns null;
        int arrayLength = 0;
        Identity groupIdValue[] = {null, null, null, null, null, null, null, null};
        //groupIdValue.

        if (groupId != null) {
            //Highlight (grey) the first group this process belongs to
            arrayLength = groupId.size();

            for (int i = 0; i < arrayLength; i++) {
                groupIdValue[i] = groupId.get(i);
            }

            //Start from the currently selected index - 1 and work up the model until an applicable group is found
            for (int listItem = mSelectedIndex - 1; listItem >= 0 && mAdditionalIdentity == null; listItem--) {
                //Loop over each index of groups applicable to this process
                for (int j = 0; j < groupId.size(); j++) {
                    if (groupIdValue[j].equals(mIdListModel.get(listItem))) {
                        mAdditionalIndex = listItem;
                        mAdditionalIdentity = mIdListModel.get(listItem);
                        break;
                    }
                }
            }

            if (mAdditionalIdentity != null) {
                selections[0] = mSelectedIndex;
                selections[1] = mAdditionalIndex;

                mProcessGroupList.setSelectedIndices(selections);
            }
        }
        return;
    }

    /**
     * Basically this method display the tables in the operation dialog screen based on a
     * particular selection criteria. If a process is selected, then the second table
     * (SelectionTable) displays the parameters of the group of the process. Third table
     * (AdditionalTable) displays the process' parameers. If the process is not associated
     * with any group, then the process' parameters are displayed in the second table
     * i.e. SelectionTable itself. When a group is directly selected from the list, then
     * the groups' parameters are displayed in SelectionTable.
     */
    public void showTables() {
        mLowerTable.clear();
        mMiddleTable.clear();

        JL_middlePanel.setText(sNoAction);
        JL_lowerPanel.setText(sNoAction);

        /* mSelectedIdentity always consists of the main selected one */
        if (mAdditionalIdentity != null) // this means a process is selected and it has a group. Group parameter 
        // values are displayed in the middle table.
        {
            Action action = mOprnObj.getAction(mAdditionalIndex + listOffsetIndex);
            mMiddleTable.setData(action);
            // mAdditionalTable.setData(action);
            JL_middlePanel.setText(sGroupParameters + mAdditionalIdentity.toString()
                    + sIdNameSeparator + action.getActionName());
            // AdditionalActionLabel.setText(mAdditionalIdentity.toString() + sIdNameSeparator + action.getActionName());

            action = mOprnObj.getAction(mSelectedIndex + listOffsetIndex);
            mLowerTable.setData(action);
            JL_lowerPanel.setText(sProcessParameters + mSelectedIdentity.toString() + sIdNameSeparator + action.getActionName());

        } else {
            if (mSelectedIdentity != null) {
                Action action = mOprnObj.getAction(mSelectedIndex + listOffsetIndex);
                mMiddleTable.setData(action);

                JL_middlePanel.setText(sSelectionParameters + mSelectedIdentity.toString()
                        + sIdNameSeparator + action.getActionName());
                //SelectionActionLabel.setText(mSelectedIdentity.toString() + sIdNameSeparator + action.getActionName());
            }
        }

        invalidate();
        repaint();
    }

    /**
     * This method is invoked when the operation drilldown screen is closed.
     */
    @Override
    public void closeWindow_actionPerformed(java.awt.event.WindowEvent evt) {
        //Actual Implementation in the classes that inherit this class
        closeWindow();
        origin.checkData();
    }

    /**
     * Closes the window.  Fallthrough is intentional, as it removes the need for
     * replicated code.
     */
    @SuppressWarnings("fallthrough")
    public void closeWindow() {
        //Make sure every table's edits are committed.
        mOperationTable.commitEdit(true);
        mMiddleTable.commitEdit(true);
        mLowerTable.commitEdit(true);

        int option = -200;

        if (dataChanged == true || notesDataChanged == true) {
            option = JOptionPane.showConfirmDialog(this, "update the current Operation info into the current management record?");
            //System.out.println("OperationDlg : closeWindow -- OPTION is : " + option );
            switch (option) {
                case JOptionPane.CANCEL_OPTION:
                    break;
                case JOptionPane.YES_OPTION:
                    
                switch(allowSave)
                {
                    case NOSAVE:
                        JOptionPane.showMessageDialog(null, "Unable to save:\nSome data out of limits.",
                        mOprnObj.getOperationName(), JOptionPane.INFORMATION_MESSAGE);
                        return;
                    case WARNSAVE:
                        JOptionPane.showMessageDialog(null, "Warning:\nSome data out of recommended limits.",
                        mOprnObj.getOperationName(), JOptionPane.INFORMATION_MESSAGE);
                    default:
                        mOperationTable.saveDataSource();
                        mMiddleTable.saveDataSource(); //i.e transfer the new data from mVDataSource to Action object (mAction)
                        mLowerTable.saveDataSource();
                        mOriginalOprnObj = mOprnObj;
//                        c_manage.fireRowChanged(c_row);
                }
                    break;
                case JOptionPane.NO_OPTION:
                    mOperationTable.resetOper();
                    mLowerTable.resetOper();
                    mMiddleTable.resetOper();
                    break;
            }
        }

        //If neither Cancel nor close option was selected, then close the window
        if (option != JOptionPane.CANCEL_OPTION && option != JOptionPane.CLOSED_OPTION) {
            this.setVisible(false);
            dispose();
        }

    }
    
    @Override
    public void JBClose_actionPerformed(java.awt.event.ActionEvent event) {
        //Save any final changes made
//        mOperationTable = mOperationTable2;
//        mMiddleTable = mMiddleTable2;
//        mLowerTable = mLowerTable2;
        
        int option = -200;
        option = JOptionPane.showConfirmDialog(this, "update the current Operation info into the current management record?");
            //System.out.println("OperationDlg : closeWindow -- OPTION is : " + option );
            switch (option) {
                case JOptionPane.CANCEL_OPTION:
                    break;
                case JOptionPane.YES_OPTION:
                    mOperationTable.commitEdit(true);
                    mMiddleTable.commitEdit(true);
                    mLowerTable.commitEdit(true);
                    break;
                case JOptionPane.NO_OPTION:
                    mOperationTable.resetOper();
                mLowerTable.resetOper();
                mMiddleTable.resetOper();
                    mOperationTable = mOperationTable2;
                    mMiddleTable = mMiddleTable2;
                    mLowerTable = mLowerTable2;
                    dataChanged = false;
            }
        
        
        mOperationTable.saveDataSource();
        mMiddleTable.saveDataSource(); //i.e transfer the new data from mVDataSource to Action object (mAction)
        mLowerTable.saveDataSource();
//        closeWindow();
        origin.checkData();
        origin.reduceOpWinOpen();
        this.setVisible(false);
            dispose();
        
        

    }

    @Override
    public void CancelButton_actionPerformed(java.awt.event.ActionEvent event) {
        
        origin.checkData();
        mOperationTable.resetOper();
        mLowerTable.resetOper();
        mMiddleTable.resetOper();
        
        origin.checkData();
        origin.reduceOpWinOpen();
        this.setVisible(false);
        dispose();

    }
boolean fallthroo = false;
    @Override
    @SuppressWarnings("fallthrough")
    public void SaveAsButton_actionPerformed(java.awt.event.ActionEvent event) {
        mOperationTable.commitEdit(true);
        mMiddleTable.commitEdit(true);
        mLowerTable.commitEdit(true);
        
       
        switch(allowSave) {
            case NOSAVE:
                if(!fallthroo){
                JOptionPane.showMessageDialog(null, "Unable to save:\nSome data out of limits.",
                mOprnObj.getOperationName(), JOptionPane.INFORMATION_MESSAGE);
                break;
                }

            case WARNSAVE:
                if(!fallthroo){
                JOptionPane.showMessageDialog(null, "Warning:\nSome data out of recommended limits.",
                mOprnObj.getOperationName(), JOptionPane.INFORMATION_MESSAGE);}
//                fallthroo = true;
            default:
                int option = -200;
                dataChanged = true;
                if (dataChanged == true || notesDataChanged == true) {
                    option = JOptionPane.showConfirmDialog(this, "Save changes made to the current Operation info into a new operation file? ");
                    switch (option) {
                        case JOptionPane.CANCEL_OPTION:
                            return;
                        case JOptionPane.NO_OPTION:
                            return;
                    }
                }
                
                String options[] = {"<html>Save with current<br>crop/residue</html>",
                    "<html>Save with no<br>crop/residue</html>"
                };
                // If the operation has a crop then ask if he wants to save the 
                // operation with the crop or without the crop - Neha.
                if (mOprnObj.hasCrop() && !fallthroo) {
                    option = JOptionPane.showOptionDialog(this, "Select an Option", "Select Save Option",
                            JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, null);
                }

                //System.out.println("OperationDlg-SaveAs-option value:"+option);
                if (option == JOptionPane.CLOSED_OPTION) {
                    return;
                }
                
//                if(fallthrough){
//                    option = JOptionPane.NO_OPTION;
//                }
//                mSaveOprnObj = (OperationObject) mOriginalOprnObj.clone();
//                            saveCropData(mSaveCropObject);
                
                //Save any final changes made
//                saveOpData(mOperationTable.)
                OperationObject mopHold = (OperationObject)mOprnObj.clone();
//                mOperationTable.
                mOperationTable.saveDataSource();
                mMiddleTable.saveDataSource(); //i.e transfer the new data from mVDataSource to Action object (mAction)
                mLowerTable.saveDataSource();
                
//                saveOpData(mSaveOprnObj);
//                dataChanged = false; //Reset changed flag after updating

                String oprnDirPath = ConfigData.getDefault().getDataParsed("CD-local_oper_folder");
                WepsFileChooser2 mfc = new WepsFileChooser2(WepsFileTypes2.Operation, oprnDirPath,
                        WepsFileChooser2.Action.Save);
                //set the tooltip of "home" button to "Home" instead of "Desktop"
                mfc.homeToolTip(mfc);
                mfc.setOperationChooser();
                mfc.enableFolderButtonsSave();
                mfc.setCurrentDirectory(oprnDirPath); //new de.schlichtherle.truezip.file.File(ConfigData.INITIAL_DIR));
                mfc.setSelectedFile(new File (mOprnObj.getOperationName() + WepsFileTypes2.Operation.getExtension()));
                
                mfc.enableCfgDefLocButton(false);
                mfc.enableDbButton(false);
                mfc.setFileFilter(WepsFileTypes2.Operation.getFileFilter());
            mfc.setDefaultDirectory(new TFile(oprnDirPath));
            
            //Below is what chooses between where filechooser opens when looking at operations.----
            boolean localCfgChecked = ConfigData.checkParmValue("CD-local_oper_cb","1");
            boolean systemCfgChecked = ConfigData.checkParmValue("CD-system_oper_cb","1");
            if(localCfgChecked){
               mfc.setCurrentDirectory(Util.parse(ConfigData.getDefault().getData(ConfigData.LocalOpDB)));
               mfc.setDefaultDirectory(new TFile(Util.parse(ConfigData.getDefault().getData(ConfigData.LocalOpDB))));
            }else if(!systemCfgChecked){
                mfc.setCurrentDirectory(Util.getProperty("project.directory"));
                mfc.setDefaultDirectory(new TFile(Util.getProperty("project.directory")));
            }
            //--------
                
                
                if(!fallthroo){
                //Set the title of the file chooser dialog appropriately acc to the option - Neha
                if (option == 0) {
                    mfc.setDialogTitle("Save a new Operation (with " + mOprnObj.getCropName() + ")");
                } else {
                    if (option == 1) {
                        mfc.setDialogTitle("Save a new Operation (with no crop)");
                    }
                }
                }
                if (mfc.showDialog(this) != WepsFileChooser2.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;
                }
                if(newFileName.endsWith("."+WepsFileTypes2.Operation.getExtension())){
                        newFileName = newFileName.substring(0, newFileName.lastIndexOf(".."))+WepsFileTypes2.Operation.getExtension();
                    }
                if (!newFileName.endsWith(WepsFileTypes2.Operation.getExtension())) {
                    newFileName = newFileName + WepsFileTypes2.Operation.getExtension();
                }
//                System.out.println("here" + newFileName);
                if (option == 0 && !fallthroo) {
                    //save with current crop/residue selected
                    mOprnObj.writeXMLFile(newFileName, true, true);
                } else {
                    if (option == 1 ||fallthroo) {
                        //save with no crop/residue
                        mOprnObj.writeXMLFile(newFileName, true, false);
//                        System.out.println("here write no crop");
                    } else {
                        //save the operation that does not have any crop
                        mOprnObj.writeXMLFile(newFileName, false, false);
                    }
                }
//                mOperationTable.resetOper();
//                mLowerTable.resetOper();
//                mMiddleTable.resetOper();
                MCREWConfig.getOpFileList().refreshFiles();
//                MCREWConfig.refreshDropdowns();
                
        }
    }
    /**
     * Saves all of the data back into the Crop Object.
     * @param pCropObject 
     */
    @SuppressWarnings("fallthrough")
    void saveOpData(OperationObject pCropObject) {
                //System.out.println("====== CROP DRILL DOWN SAVE ======");
        //Check allowSave status
        switch(allowSave)
        {
            case NOSAVE:
                JOptionPane.showMessageDialog(null, "Unable to save:\nSome data out of limits.",
                mOprnObj.getCropName(), JOptionPane.INFORMATION_MESSAGE);
//                scrollToTab();
                break;
            case WARNSAVE:
                JOptionPane.showMessageDialog(null, "Warning:\nSome data out of recommended limits.",
                mOprnObj.getCropName(), JOptionPane.INFORMATION_MESSAGE);
            default:
//                cParams = pCropObject.getCategoryParams();
                
                for (int i = 0; i < mOperationTable.parameterNames.size(); i++) {
//                    String cName = JTP_main.getTitleAt(i);
                    String para = mOperationTable.parameterNames.get(i);
//                    mOperationTable
//                    myParamVec = (Vector<String>) cParams.get(cName.trim());
//                    ParamJCTable table = tabTableMap.get(cName);
                    if (mOperationTable != null) {
//                        mOperationTable.saveTableDataSource(pCropObject, para);
                    } else {
                        throw new RuntimeException("Trying to save to a table that does not exist. '" + para + "'");
                    }
                }
//                for (int i = 0; i < JTP_main.getTabCount(); i++) {
//                    String cName = JTP_main.getTitleAt(i);
//                    myParamVec = (Vector<String>) cParams.get(cName.trim());
//                    ParamJCTable table = tabTableMap.get(cName);
//                    if (table != null) {
//                        table.saveTableDataSource(pCropObject, myParamVec);
//                    } else {
//                        throw new RuntimeException("Trying to save to a table that does not exist. '" + cName + "'");
//                    }
//                }
//                for (int i = 0; i < JTP_main.getTabCount(); i++) {
//                    String cName = JTP_main.getTitleAt(i);
//                    myParamVec = (Vector<String>) cParams.get(cName.trim());
//                    ParamJCTable table = tabTableMap.get(cName);
//                    if (table != null) {
//                        table.saveTableDataSource(pCropObject, myParamVec);
//                    } else {
//                        throw new RuntimeException("Trying to save to a table that does not exist. '" + cName + "'");
//                    }
//                }
            }
    }

    /**
     * This method adjust the components in the operation dialog so that the adjoining 
     * components are spaced uniformly w.r.t each other when a window or frame is 
     * resized.
     * @param evt The resize event that occurs on the window.
     */
    @Override
    public void OperationDlgN_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 -= 30;
        JP_main.setSize(size);

        JP_toolbar.setSize(JP_main.getWidth() - sideOffset, 40);
        JP_toolbar.setLocation(componentOffSet, componentOffSet);

        JP_operationName.setSize(JP_main.getWidth() - sideOffset, 30);
        JP_operationName.setLocation(componentOffSet, (JP_toolbar.getHeight() + (2 * componentOffSet)));

        size.height -= (JP_operationName.getHeight() + JP_toolbar.getHeight() + (5 * componentOffSet));
        int yLocation = (JP_operationName.getHeight() + JP_toolbar.getHeight() + (3 * componentOffSet));

        JP_operDetails.setSize((((int) size.getWidth() / 3) - sideOffset), (int) size.getHeight());
        JP_operDetails.setLocation(sideOffset, yLocation);

        JSP_list.setSize((JP_operDetails.getWidth() - sideOffset), (JP_operDetails.getHeight()
                - (JL_Date.getHeight() + JLabel1.getHeight() + 5 * componentOffSet)));
        JSP_list.setLocation(componentOffSet, (JL_Date.getHeight() + JLabel1.getHeight() + 4 * componentOffSet));

        JP_upper.setSize(((((int) size.getWidth() * 2) / 3) - (2 * sideOffset)),
                (JP_operDetails.getHeight() / 3 - (3 * componentOffSet)));
        JP_upper.setLocation((JP_operDetails.getWidth() + 2 * sideOffset), yLocation);
        JSP_upperParam.setSize((JP_upper.getWidth() - sideOffset), (JP_upper.getHeight()
                - (JP_upperParams.getHeight() + componentOffSet)));

        JP_middle.setSize(JP_upper.getWidth(), JP_upper.getHeight());
        JP_middle.setLocation((JP_operDetails.getWidth() + 2 * sideOffset),
                (yLocation + JP_upper.getHeight() + componentOffSet));
        JSP_middleParam.setSize((JP_middle.getWidth() - sideOffset),
                (JP_middle.getHeight() - (JP_middleParam.getHeight() + 2 * componentOffSet)));

        JP_lower.setSize(JP_upper.getWidth(), JP_upper.getHeight());
        JP_lower.setLocation((JP_operDetails.getWidth() + 2 * sideOffset),
                (yLocation + 2 * (JP_upper.getHeight() + componentOffSet)));
        JSP_lowerParam.setSize((JP_lower.getWidth() - sideOffset),
                (JP_lower.getHeight() - (JP_lowerParam.getHeight() + 2 * componentOffSet)));

        validate();
        repaint();

    }

    class CustomCellRenderer extends JLabel implements ListCellRenderer<Identity> {

        private static final long serialVersionUID = 1L;

        /**
         * 
         * @param list
         * @param value identity value from which Actionname is to be displayed
         * @param index cell index
         * @param isSelected is the cell selected
         * @param cellHasFocus the list and the cell have the focus
         */
        @Override
        public Component getListCellRendererComponent(
                JList<? extends Identity> list,
                Identity value,
                int index,
                boolean isSelected,
                boolean cellHasFocus) {
            String actionName = "";
            ActionMeta actionMeta = MCREWConfig.getObjectMeta(XMLConstants.soperation).getActionMeta(value);
            if (actionMeta != null) {
                actionName = actionMeta.getActionName();
            }

            setText(value + sIdNameSeparator + actionName);

            
            if(outTab.contains(value))
            {
                setBackground(Color.MAGENTA);
                setForeground(list.getForeground());
            }
            else
            {
                if (isSelected) {
                if ((value).equals(mSelectedIdentity)) {
                    setBackground(list.getSelectionBackground());
                    setForeground(list.getSelectionForeground());
                } else {
                    setBackground(Color.lightGray);
                    setForeground(list.getForeground());
                }
            } else {
                setBackground(list.getBackground());
                setForeground(list.getForeground());
            }
            }
            setEnabled(list.isEnabled());
            setFont(list.getFont());
            setOpaque(true);
            return this;
        }
    }

    class ListMouseAdapter extends MouseAdapter {

        @Override
        public void mouseClicked(MouseEvent e) {
            int SelectedIndex = mProcessGroupList.locationToIndex(e.getPoint());
            if ((SelectedIndex >= mIdListModel.getSize()) || (SelectedIndex < 0)) {
                return;
            }
            mSelectedIndex = SelectedIndex;
            mSelectedIdentity = mIdListModel.get(mSelectedIndex);
            setAllSelections();
            // Now before changing the data, the table values must be stored as the user might have changed the values.
            if (mMiddleTable.tableDataChanged == true) {
                mMiddleTable.saveDataSource(); //i.e transfer the new data from mVDataSource to Action object (mAction)
            }

            if (mLowerTable.tableDataChanged == true) {
                mLowerTable.saveDataSource();
            }

            showTables();
        }
    }

    static class ActionTableCSHManager implements CSH.Manager {

        private ActionJCTable c_table;

        public ActionTableCSHManager(ActionJCTable 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.parameterNames.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 ActionJCTable extends JCTable implements JCEditCellListener, MouseMotionListener {

        private static final long serialVersionUID = 1L;

        public int YtoRow2(int y) {
            return YtoRow(y);
        }
        public String mHeaderRow[] = {"Parameter", "Value", "Units"};
        int PROMPTCOLUMN = 0;
        int VALUECOLUMN = 1;
        int UNITSCOLUMN = 2;
        //This is used to check if theres a need for saving data from VDataSource to the action object
        boolean tableDataChanged = false;
        JCEditableVectorDataSource mVDataSource;
        JCCellStyle mCellStyle, mUnHLimitCellStyle, mUnSLimitCellStyle, mValueCellStyle, mHLimitCellStyle, mSLimitCellStyle;
        Action mAction; // Specifies the action for which the data is being displyed
        Action mAction2;
        JCStringCellEditor se;
        List<NotesOperation> notes = new ArrayList<NotesOperation>();
        List<Integer> noteMap = new ArrayList<Integer>();
        OperationDlg parentDlg;

        public ActionJCTable(OperationDlg parentDlg) {
            this();
            this.parentDlg = parentDlg;
            CSH.addManager(new ActionTableCSHManager(this));
        }

        public ActionJCTable() {
            mVDataSource = new JCEditableVectorDataSource();
            setDataSource(mVDataSource);
            setTableLooks();
            getDataSource().addTableDataListener(new JCTableDataListener() {

                @Override
                public void dataChanged(JCTableDataEvent event) {
                     int row = event.getRow();
                    int column = event.getColumn();
//            String paramName = getParamName(row);
//                    afterEditValue = (String) event.getSource().toString() .getDataSource().getTableDataItem(row, column);
                    ////System.out.println("Data Changed handler");
                    if (event.getCommand() == JCTableDataEvent.CHANGE_VALUE) {
                        tableDataChanged = true;
//                        System.out.println("heredatachangedop" + ((JCEditableVectorDataSource)event.getSource()).getTableDataItem(row, column));
                    }
                }
            });
            mAction = null;
            mAction2 = null;
            addEditCellListener(this);
            addMouseMotionListener(this);

        }

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

        @Override
        public void mouseDragged(MouseEvent mouseEvent) {
            return;
        }

        @Override
        public void focusGained(FocusEvent ev) {
//            System.out.println("herefocusgainedop");

        }

        @Override
        public void focusLost(FocusEvent ev) {
            Component comp = ev.getOppositeComponent();
//            mLowerTable.selectAll();
//            System.out.println("herefocuslost"+ this.getDataSource().getTableDataItem(beforeEditRow, beforeEditCol));
//            mLowerTable.commitEdit(true);
            this.afterEditCell(beforeCellEvent);
//            if (e.getOppositeComponent().getParent() != table) {
//            loseCellFocus();
//        }
            //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();
                    }
                }
                return;
            }
        }
        String beforeEditValue = "";
        String afterEditValue = "";
        JCEditCellEvent beforeCellEvent = null;
        int beforeEditRow = -1;
        int beforeEditCol = -1;
        
        @Override
        public void beforeEditCell(JCEditCellEvent ev) {
            int row = ev.getRow();
            int column = ev.getColumn();
            System.out.println("beforeCelledit");
            beforeEditCol = ev.getColumn();
            beforeEditRow = ev.getRow();
            beforeCellEvent = ev;
            beforeEditValue = (String) this.getDataSource().getTableDataItem(row, column);
        }

        @Override
        public void editCell(JCEditCellEvent ev) {
            System.out.println("EditCell");
              beforeEditRow = ev.getRow();
              beforeEditCol = ev.getColumn();
        }

        @Override
        public void afterEditCell(JCEditCellEvent ev) {
            int row = ev.getRow();
            int column = ev.getColumn();
            String paramName = getParamName(row);
            String evsrc ="";
            ((ActionJCTable)ev.getSource()).commitEdit(false);
            afterEditValue = (String) this.getDataSource().getTableDataItem(row, column);
            if (beforeEditValue != null && afterEditValue != null) {
                //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) == false) {
                    tableDataChanged = true;
                    dataChanged = true;
//                    mLowerTable.commitEdit(true);
                }
            }
//            mLowerTable.saveDataSource();
            InputLimits.TableStatus check = checkDataCell(afterEditValue, paramName);
            test(check, row);
        }

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

            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);

            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);
            }

            //set the cell editor for all the editable cells - neha
            mValueCellStyle.setCellEditor(se);
            se.addFocusListener(this);

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

            setMinWidth(JCTableEnum.ALL, 150);	// default width
            setMinWidth(0, 250);					// make param prompt wider
            setMinWidth(2, 100);
            setFocusColor(Color.red);

            mVDataSource.setColumnLabels(mHeaderRow);
            mVDataSource.setNumColumns(mHeaderRow.length);
            mVDataSource.setNumRows(0);
        }

         private void test(InputLimits.TableStatus cellStatus, int row)
        {
            String paramName = getParamName(row);
            String displayAttribute = "";
            String valueAttribute = "";
            for(Action token : mOprnObj.getAllActions())
            {
                try
                {
                    ActionMeta actionMeta = MCREWConfig.getObjectMeta(XMLConstants.soperation).getActionMeta(token.getIdentity());
                    ParameterMeta limits = actionMeta.getParameterMeta(paramName);
                    displayAttribute = limits.getGroupAttribute(token.getActionName(), XMLConstants.sdisplayattribute);
                    valueAttribute = limits.getGroupAttribute(token.getActionName(), XMLConstants.svalueattribute);
                }
                catch(NullPointerException incorectAction){}
            }
            if(!valueAttribute.equals("N")) return;
            switch(cellStatus)
            {
                case WARNSAVE:
                    setCellStyle(row, VALUECOLUMN, mSLimitCellStyle);
                    if(displayAttribute.equals("V")) setCellStyle(row, VALUECOLUMN, mUnSLimitCellStyle);
                    if(!outSoft.contains((Integer) row))
                    {
                        outSoft.add(row);
                        if(outHard.contains((Integer) row))
                        {
                            int toRemove = outHard.indexOf(row);
                            outHard.remove(toRemove);
                            if(outHard.isEmpty())
                            {
                                allowSave = InputLimits.TableStatus.WARNSAVE;
                            }
                        }
                        if(allowSave == InputLimits.TableStatus.OKAY)
                        {
                            allowSave = InputLimits.TableStatus.WARNSAVE;
                        }
                        if(allowSave == InputLimits.TableStatus.NOSAVE
                                && outHard.isEmpty())
                        {
                            allowSave = InputLimits.TableStatus.WARNSAVE;
                        }
                    }
                    break;
                case NOSAVE:
                    setCellStyle(row, VALUECOLUMN, mHLimitCellStyle);
                    if(displayAttribute.equals("V")) setCellStyle(row, VALUECOLUMN, mUnHLimitCellStyle);
                    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);
                    if(displayAttribute.equals("V")) setCellStyle(row, VALUECOLUMN, mCellStyle);
                    if(outHard.contains((Integer) row))
                    {
                        int toRemove = outHard.indexOf(row);
                        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;
                    }
                    if(outHard.isEmpty() && !outSoft.isEmpty())
                    {
                        allowSave = InputLimits.TableStatus.WARNSAVE;
                    }
                    if(outSoft.isEmpty() && !outHard.isEmpty())
                    {
                        allowSave = InputLimits.TableStatus.NOSAVE;
                    }

                }
            if(!outHard.isEmpty() || !outTab.isEmpty()) allowSave = InputLimits.TableStatus.NOSAVE;
        }
        
        /* 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();
            mAction = null;
            mAction2 = null;
            mVDataSource.setNumRows(0);
        }
        protected List<String> parameterNames;
        
        public String getParamName(int row)
        {
            return parameterNames.get(row);
        }
        
        public void setThing(String eye){
//            System.out.println("hhh" +eye);
            bbb = eye;
        }
        String bbb = "";
        boolean bb = false;
        int rowww = -1;
        int colll = -1;
        String abc = "";
        String parmmmm = "";
        public void setBB(boolean b){
            bb = true;
        }
        Action oldAct = null;
        @SuppressWarnings("rawtypes") //"here is a temporary removal of warning"
        JComboBox comboBoxxx = null;
        public void setBB(String get, int row, int i){
            parmmmm = get;
            rowww = row;
            colll = i;
            bb = true;
        }
      
        public void setData(Action pAction) {
            mAction = pAction;
            mAction2 = pAction;
            parameterNames = new ArrayList<String>(mAction.getParameterNames());
            int numParams = parameterNames.size();

            if (numParams == 0) {
                System.err.println("ParamterJCTable:setData(): " + "Action " + pAction.getIdentity() + " has no parameters");
                mVDataSource.clearCells();

                return;
            }

            ActionMeta actionMeta = MCREWConfig.getObjectMeta(XMLConstants.soperation).getActionMeta(mAction.getIdentity());
            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;
            
            int numHidden = 0;

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

                String paramPrompt = null;
                String displayAttribute = null;
                String valueAttribute = null;
                String format = null;
                String units = null;
                Hashtable<String, String> paramChoices = null;

                ParameterMeta paramMeta = null;
                Parameter parameter = mAction.getParameter(paramName);

                //paramName = parameter.get(XMLConstants.sname);
                paramValue = parameter.get(XMLConstants.svalue);

                // Col 0 = param prompt, Col 1 = param value, Col 2 = param units
                if (actionMeta != null) {
                    paramMeta = actionMeta.getParameterMeta(paramName);
                    if (paramMeta != null) {
                        paramPrompt = paramMeta.getPrompt(); // actionMeta.getParamPrompt(paramName);
                        //paramType = paramMeta.getType(); // actionMeta.getParamType(paramName);

                        units = paramMeta.getUnit(MCREWConfig.getDisplayUnit());
                        if (units == null) {
                            units = paramMeta.getUnit(XMLConstants.kPrimaryUnit);
                        }
                        displayAttribute = paramMeta.getAttribute(XMLConstants.sdisplayattribute);
                        valueAttribute = paramMeta.getAttribute(XMLConstants.svalueattribute);
                        format = paramMeta.getAttribute(XMLConstants.sformat);

                        paramChoices = paramMeta.getChoices();
                    }
                }

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

                }

                if (valueAttribute == null) {
                    System.err.println("OperationDlg:setData(): " + "Theres no value attribute for parameter "
                            + paramName + " in the *.lang.xml file");
                    valueAttribute = XMLConstants.sint;
                }

                if ((paramPrompt == null) || (paramPrompt.length() == 0)) {
                    paramPrompt = paramName;
                }

                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.
                 */
                if (valueAttribute.equals(XMLConstants.schoice)) //(paramType.equals(XMLConstants.schoice)) )
                {
                    if (paramChoices == null) // due to reason such as parameter misspelled in lang file,...
                    {
                        System.err.println("OperationDlg:setData(); " + paramName + " has no Choices");
                        continue;
                    }

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

                    List<String> choiceList = new ArrayList<>();
                    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();
                    // JCCellStyle comboStyle = new JCCellStyle((JCCellStyle)getDefaultCellStyle().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);
                    @SuppressWarnings("rawtypes")
                    JComboBox comboBox = (JComboBox) ((comboStyle.getCellEditor()).getComponent());
                    
                    comboBoxxx = comboBox;
                    ssholderComboChoices.put(paramName,comboBoxxx);
                    
                    abc = (String) comboBox.getSelectedItem();
                    for(int ii =0; ii > comboBox.getItemCount(); ii++){
                        if(comboBox.getItemAt(ii).equals(abc)){
//                            System.out.println("herree");
                        }
                    }
                    if(abc!=null){
//                        System.out.println("herrE" + comboBox.getItemCount());
                        ssholderPrevChoice.put(paramName,abc);
                        ssholderPrevChoice.put(paramName,"1");
                    }
                    
                    comboBox.addItemListener(new ItemListener() {
                        

                        @Override
                        public void itemStateChanged(ItemEvent ev) {
                            
                            if (ev.getStateChange() == ItemEvent.SELECTED) {	////System.out.println("Item changed");
//                                System.out.println("here43" + ev.getItem());
                                commitEdit(true);
//                                setThing(ev.getItem().toString());
                                
                            }else{
                                setThing(ev.getItem().toString());
                                
//                                ssholder.put(paramName, ev.getItem().toString());
                                setBB(true);
                                oldAct = pAction;
//                                System.out.println(ssComboBoxValueHolder.size()+"here99 "+ssholder.size());
                                for(int i = 0; i < comboBox.getItemCount(); i++){
                                    if(comboBox.getItemAt(i).equals(ev.getItem().toString())){
                                        ssComboBoxLocationHolder.put(paramName,i);
                                    }
                                }
                                
                                bbb = ev.getItem().toString();
                                ssComboBoxValueHolder.put(paramName,bbb);
//                                System.out.println(ssComboBoxValueHolder.size()+"here79 "+ssholder.size());
                            }
                        }
                    });
                    
                    
                    mVDataSource.setTableDataItem(paramChoices.get((paramValue)), row, col++);
                    setBB(paramChoices.get((paramValue)), row, col++);
                    /* END TEMPORARY SOLUTION*/

                } else if (valueAttribute.equals(XMLConstants.smultiline)) {
                    //System.out.println("SetData:MultiLine Text attribute for NOTES");
                    
                    int index = notes.size();
                    notes.add(new NotesOperation("Operation File Notes "+paramName, parentDlg, this, paramValue, row, col));
                    noteMap.add(row);

                    JCCellStyle buttonStyle = (JCCellStyle) mValueCellStyle.clone();
                    buttonStyle.setCellEditor(new CropDlg.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.get(index).setEditable(true);
                    } else {
                        button.setText("View Notes");
                        notes.get(index).setEditable(false);
                    }

                    buttonStyle.setCellRenderer(new CropDlg.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++);
                } else if (valueAttribute.equals(XMLConstants.sfuel)) {
                    FuelComboBoxEditor fuelEditor = new FuelComboBoxEditor();
                    FuelComboBoxRenderer fuelRenderer = new FuelComboBoxRenderer();

//                    fuelEditor.setSelectedItem(paramChoices.get(paramValue));
//                    fuelRenderer.setSelectedItem(paramChoices.get(paramValue));
                    JCCellStyle fuelStyle = (JCCellStyle) mValueCellStyle.clone();
                    // JCCellStyle comboStyle = new JCCellStyle((JCCellStyle)getDefaultCellStyle().clone());
                    fuelStyle.setCellEditor(fuelEditor);
                    fuelStyle.setCellRenderer(fuelRenderer);
                    if ((displayAttribute != null) && (displayAttribute.equals(XMLConstants.sEditable))) {
                        fuelStyle.setEditable(true);
                    } else {
                        fuelStyle.setEditable(false);
                        fuelStyle.setBackground(MCREWConfig.getDisabledColor());
                    }

                    setCellStyle(row, col, fuelStyle);
                    //set the value
                    mVDataSource.setTableDataItem(paramValue, row, col++);

                    final FuelChooser fuelChooser = (FuelChooser) ((fuelStyle.getCellEditor()).getComponent());
                    fuelChooser.addItemListener(new ItemListener() {

                        @Override
                        public void itemStateChanged(ItemEvent ev) {
                            if (ev.getStateChange() == ItemEvent.SELECTED) {	////System.out.println("Item changed");
                                commitEdit(true);
                            }
                        }
                    });
                } 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);
                    }

                    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);

                    }
                    mVDataSource.setTableDataItem(paramValue, row, col++);

                }

                mVDataSource.setTableDataItem(units, row, col++);
                InputLimits.TableStatus check = checkDataInit(row, parameterNames);
                test(check, row);
                //	mVDataSource.setTableDataItem(primaryUnit, row , col++);		
                row++;

            }
//            System.out.println("here3" +colll+ parmmmm + rowww);
            /*
             if(numRows > 0)
             mVDataSource.setNumRows(numRows);
             else
             mVDataSource.setNumRows(1); //show atleast 1 row, else the headers disappear
             */
            mVDataSource.setNumRows(row);
            checkTabInit();

        }

        public void notesButton_clicked(java.awt.event.ActionEvent evt) {
            int row = getCurrentRow();
            int col = getCurrentColumn();
            String text = (String) getDataSource().getTableDataItem(row, col);
            NotesOperation note = notes.get(noteMap.indexOf(row));
            note.setText(text);
            if (note.notesPresent == false) {
                note.setVisible(true);
                note.notesPresent = true;
            } else {
                if (note.isActive() == false) {
                    note.toFront();
                    note.setVisible(true);
                    note.requestFocus();
                }//end of else
            }
        }
        
         /**
     * Saves all of the data back into the Crop Object.
     * @param pCropObject 
     */
//    @SuppressWarnings("fallthrough")
//    void saveOpData(OperationObject pCropObject) {
//                //System.out.println("====== OP DRILL DOWN SAVE ======");
//                List<Action> cActs = pCropObject.getActs();
////                cParams = pCropObject.getCategoryParams();
//                for (int i = 0; i < JTP_main.getTabCount(); i++) {
//                    String cName = JTP_main.getTitleAt(i);
//                    myParamVec = (Vector<String>) cParams.get(cName.trim());
//                    ParamJCTable table = tabTableMap.get(cName);
//                    if (table != null) {
//                        table.saveTableDataSource(pCropObject, myParamVec);
//                    } else {
//                        throw new RuntimeException("Trying to save to a table that does not exist. '" + cName + "'");
//                    }
//                }
//            
//    }
        
        Hashtable<String,String> ssholder = new Hashtable<String,String>();
        Hashtable<String, String> ssComboBoxValueHolder = new Hashtable<>();
        Hashtable<String, Integer> ssComboBoxLocationHolder = new Hashtable<>();
        
        @SuppressWarnings("rawtypes")
        Hashtable<String,JComboBox> ssholderComboChoices = new Hashtable<String,JComboBox>();
        Hashtable<String,String> ssholderPrevChoice = new Hashtable<String,String>();
public Map<String, List<String>> cParams = new Hashtable<String, List<String>>();
        /* Saves the new values from the dataSource into the Action (mAction) object
         *
         */
        @SuppressWarnings("fallthrough")
        public void saveDataSource() {
            /* When the table data is commited, only the data in mVDataSource is saved. The data in the mAction object
             * isn't modified.
             * 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 (mAction == null) {
                return;
            } // Theres no data in the table

            if (tableDataChanged == false) {
                return;
            }

            tableDataChanged = false; //reset the boolean varaible
            List<String> parameterNames = mAction.getParameterNames();
            int numParams = parameterNames.size();
            int row = 0; /* Note that row is != numParams as some prameters might be hidden */

            ActionMeta actionMeta = MCREWConfig.getObjectMeta(XMLConstants.soperation).getActionMeta(mAction.getIdentity());

            // 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 = mAction.getParameter(paramName);
                if (parameter == null) {
                    System.err.println("OprnDlg:setData(): " + "Theres no parameter value for parameter " + paramName);
                    continue;
                }

                String oldValue = parameter.get(XMLConstants.svalue);
                if (actionMeta != null) {
                    paramMeta = actionMeta.getParameterMeta(paramName);
                    if (paramMeta != null) {
                        displayAttribute = paramMeta.getAttribute(XMLConstants.sdisplayattribute);
                        valueAttribute = paramMeta.getAttribute(XMLConstants.svalueattribute);
                        paramChoices = paramMeta.getChoices();
                    }
                }

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

                String newValue = (String) mVDataSource.getTableDataItem(row, VALUECOLUMN);
                row++;
                if (newValue == null) {
                    continue;
                }

                /* 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))) {

                    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);
                        String pastVal = parameter.get(paramName);
//                        System.out.println("here");
//                        System.out.println("keyval:" +keyVal + "\n tocompare: " +toCompare + "\n newvalue: " + newValue);
//                        System.out.println("pastVal: " + pastVal);
                        if (toCompare.equals(newValue)) {
                            parameter.setValue(keyVal);
                            ssholder.put(paramName, keyVal);
//                            ssComboBoxValueHolder.put(paramName,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);
                        }
                    }

                    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);
                        ssholder.put(paramName, oldValue);
                    }
                } // else all other types

            } // end of for
//            ssholder.keySet()

            
//            parameter = mAction.getParameter(ssholder);
        }
        
        
        public void resetOper(){
            
            if(mAction != null){
                Parameter parameter = null;
              Parameter parameter2 = null;
//              for(String sss: ssComboBoxValueHolder.keySet()){
//                  parameter2 = mAction.getParameter(sss);
//                  if(parameter!=null){
//                      for(int i = 0; i < ssholderComboChoices.get(sss).getItemCount(); i++){
//                          if(ssholderComboChoices.get(sss).getItemAt(i).equals(ssComboBoxValueHolder.get(sss))){  
//                              System.out.println("her111e");
//                               parameter2.setValue(String.valueOf(i));
//                          }
//                      }
//                        
//                    }
//              }
                for(String sss: ssholder.keySet()){
//                    System.out.println("here"+sss);
                    if(sss.contains("flag")){
                        // comboBoxxx.getItemCount()
                        parameter2 = mAction.getParameter(sss);
                        
//                        System.out.println(ssholderPrevChoice.get(sss)+"hereyo: "+ssholder.get(sss));
                        for(int i = 0; i < ssholderComboChoices.get(sss).getItemCount(); i++){

                            //if the item in ssholder2 is the same as the object that was selected
//                            System.out.println("herparam" + parameter2.getValue());
//                            parameter2.setValue("1");
//                            System.out.println("hereparamagain" + parameter2.getValue());
//                            System.out.println("here123" + ssholderComboChoices.get(sss).getItemAt(i)+"  :"+ssholderPrevChoice.get(sss) + "   :" + ssholder.get(sss));
//                            if(ssholderComboChoices.get(sss).getItemAt(i).equals(ssholderPrevChoice.get(sss))){
//                            System.out.println( ssComboBoxValueHolder.get(sss)+"herevalueholder");
//                            System.out.println("herecombolocation" + ssComboBoxLocationHolder.get(sss));
                            if(ssholderComboChoices.get(sss).getItemAt(i).equals(ssComboBoxValueHolder.get(sss))){    
                                
                                parameter = mAction.getParameter(sss);
//                                System.out.println("before: " +parameter.getValue());
                                if(parameter!=null){
                                if(sss.equals("kilflag")){
                                    if(i == 0){parameter.setValue("2");}
                                    if(i == 1){parameter.setValue("1");}
                                    if(i == 2){parameter.setValue("3");}
                                    if(i == 3){parameter.setValue("0");}
                                    ssholderComboChoices.get(sss).setSelectedItem(String.valueOf(i));
                                    
                                }else{
                                    parameter.setValue(String.valueOf(i));
                                    ssholderComboChoices.get(sss).setSelectedItem(String.valueOf(i));
                                }}
//                                parameter.setValue(String.valueOf(i));
//                                parameter.setValue();
                                //ssholderComboChoices.get(sss).setSelectedItem(String.valueOf(i));
                                //.setSelectedIndex(i);
//                                System.out.println(i+"after: " +parameter.getValue());
                                
                            }
                        }
//                        mVDataSource.setTableDataItem(parmmmm, rowww, colll);
//                        System.out.println("here8" + comboBoxxx.getSelectedItem());
                    }
                    else{
                    parameter = mAction.getParameter(sss);
                    if(parameter!=null){
//                        System.out.println("here");
                        parameter.setValue(ssholder.get(sss));
                    }
                    }
                }
            }
        }
    }
    
    static class NotesOperation extends usda.weru.mcrew.gui.NotesMan_n {

        private static final long serialVersionUID = 1L;

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

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

        @Override
        public void JBSave_actionPerformed(java.awt.event.ActionEvent evt) {
            paramValue = JTA_Notes.getText();
            tableRef.mVDataSource.setTableDataItem(paramValue, row, col);
            notesPresent = false;

            this.dispose();
        }

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

        public void setText(String text) {
            JTA_Notes.setText(text);
            tableRef.parentDlg.notesDataChanged = true;
        }

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