package usda.weru.mcrew;

import com.klg.jclass.table.JCTableDataEvent;
import com.klg.jclass.table.JCTableDataListener;

import de.schlichtherle.truezip.file.TFile;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.awt.EventQueue;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.help.CSH;
import javax.help.HelpBroker;
import javax.help.HelpSet;
import javax.swing.Icon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import javax.swing.MenuElement;

import org.apache.log4j.Logger;

import usda.weru.mcrew.gui.TablePanel_n;
import usda.weru.resources.Resources;
import usda.weru.util.ConfigData;
import usda.weru.util.Util;
import usda.weru.util.WepsFileChooser;
import usda.weru.util.WepsFileTypes;
import usda.weru.weps.RunFileData;

/**
 * This is the main classs for the MCREW (Management/Crop Rotation Editor for WEPS)
 * and will serve as the entry point for it. It also sets up
 * the management and has all the functions associated with it.
 *
 * The visual components are derived from Mcrew_b.java class author : Sudhir Kaul, Sada, Manmohan
 * date : Dec 2004
 */
public class TablePanel extends TablePanel_n implements ActionListener, ItemListener, JCTableDataListener {

    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = Logger.getLogger(TablePanel.class);
    /**
     * This flag is not being used currently.
     */
    private String refreshMcrewScreen = "false";
    /**
     * Use this flag when running MCREW in standalone mode.
     */
    private boolean standaloneFlg = false;

    /**
     * This flag tells if the label was set for the MCREW screen.
     */
    private boolean c_labelState = false;
    
    public static final Icon rotMode = Resources.getIcon("MCREWRot.png");
    public static final Icon intMode = Resources.getIcon("MCREWInt.png");
    
    private MCREWWindow coordinator;

    /**
     * Tells whether the modified data from crop, operation or main MCREW table was saved
     * successfully in the underlying datastructure.
     */
    public boolean saveSuccess = false;
    /**
     * This string tells us the whether the file to be saved has a title or not.
     */
    public static final String sUntitledFileName = "Untitled";
    /**
     * This is the version of this software & not of the man files
     */
    public static final String sVersionLine = "Version: 1.1";
    /**
     * Sets the default extension for the files that are saved in.
     */
    public static final String sDefaultFileExtension = XMLConstants.sWepsFileExtension;
    /**
     * Directory path where the files are saved.
     */
    public  String savePath = "";
    /**
     * Absolute Template directory path
     */
    public String saveTemplatePath;
    /**
     * Name of the present open Management file in Mcrew
     */
    public String fileName = null;
    /**
     * Name of the absolute path of the Present SAVED Management file in Mcrew so that this can be
     * sent to AuxPanel
     */
    public String absFileName = null;
    /**
     * Name of the absolute path of the present Management file OPENED in MCREW
     */
    public String filePathName = null;
    /**
     * Table object associated with the main MCREW screen and the subsequent Crop & operation dialog
     * screens that hold the data in various rows.
     */
    Table table;
    /**
     * Notes related to Weps manageent file go here in the text area held by this dialog box which
     * can be pulled any time and modifications made here are saved for future retrival.
     */
    public NotesMan notes;
    /**
     * Minimum Width of the main MCREW screen. Cannot reduce the scrren width below this width even
     * if done manually.
     */
    public static final int MIN_WIDTH = 630;
    /**
     * Minimun Height of the main MCREW screen. Cannot reduce the scrren height below this height
     * even if done manually.
     */
    public static final int MIN_HEIGHT = 380;
    /**
     * Side offsets used when the MCREW frame is resized and other components sitting in the
     * container are to be automatically resized to make the application look evenly spaced in with
     * reference the edges.
     */
    public static final int sideOffSet = 10;
    /**
     * Component offset is used when the MCREW frame is resized and other components sitting in the
     * container are to be automatically resized and spaced for uniformity with respect to the
     * adjecent components in the container.
     */
    public static final int componentOffSet = 5;
    /**
     * Popup is the default popup menu which is shown on single /multiple row selections.
     */
    private JPopupMenu popup;

    /**
     *
     * @return
     */
    public JPopupMenu getPopup() {
        return popup;
    }
    /**
     * datePopup is the default popup menu which is shown on single /multiple row selections in the
     * date column of the main MCREW table.
     */
    private JPopupMenu datePopup;

    /**
     *
     * @return
     */
    public JPopupMenu getDatePopup() {
        return datePopup;
    }
    /**
     * Popup for operation cell to get to the operation dialog box or accessing the functions
     * provided for the operation cell in main MCREW screen. This popup is the default popup menu
     * which is shown on single /multiple row selections in the operation column of the main MCREW
     * table.
     */
    private JPopupMenu operationCellPopup;

    /**
     *
     * @return
     */
    public JPopupMenu getOperationPopup() {
        return operationCellPopup;
    }
    /**
     * Popup for crop cell to get to the crop dialog box or accessing the functions provided for the
     * crop cell in main MCREW screen. This popup is the default popup menu which is shown on single
     * /multiple row selections in the crop column of the main MCREW table.
     */
    private JPopupMenu cropCellPopup;

    /**
     *
     * @return
     */
    public JPopupMenu getCropPopup() {
        return cropCellPopup;
    }
    /**
     * Popup for tillage cell of a crop to access the update functions for the tillage operation in
     * main MCREW screen. This popup is the default popup menu which is shown on single row
     * selections in the tillage column of the main MCREW table.
     */
    private JPopupMenu tillageCellPopup;

    /**
     *
     * @return
     */
    public JPopupMenu getTillagePopup() {
        return tillageCellPopup;
    }
    /**
     * These vectors are created when the requirement to show combined menus arise. i.e for eg When
     * a complete row(s) is(are) selected and the user right clicks in the operation column, then it
     * should display a combination of operationCellPopup and operationPopup. The combination of
     * thse two menu have to be created every time, or after the first time, the individual popup or
     * operationCellPopup will show nothing Also, showing one menu directly below the other will not
     * work either.
     */
    private Vector<MenuElement> popupVec;

    /**
     *
     * @return
     */
    public List<MenuElement> getPopupElements() {
        return popupVec;
    }
    /**
     * Holds all the pop-up options for the right click event on the cells in date column
     */
    private Vector<MenuElement> datePopupVec;

    /**
     *
     * @return
     */
    public List<MenuElement> getDatePopupElements() {
        return datePopupVec;
    }
    /**
     * Holds all the pop-up options for the right click event on the cells in operation column
     */
    private Vector<MenuElement> operationCellPopupVec;

    /**
     *
     * @return
     */
    public List<MenuElement> getOperationPopupElements() {
        return operationCellPopupVec;
    }
    /**
     * Holds all the pop-up options for the right click event on the cells in crop column
     */
    private Vector<MenuElement> cropCellPopupVec;

    /**
     *
     * @return
     */
    public List<MenuElement> getCropPopupElements() {
        return cropCellPopupVec;
    }
    /**
     * Holds all the pop-up options for the right click event on the cells in tillage column
     */
    private Vector<MenuElement> tillageCellPopupVec;

    /**
     *
     * @return
     */
    public List<MenuElement> getTillagePopupElements() {
        return tillageCellPopupVec;
    }

    private MouseListener popupListener;
    private boolean calibIcon = false;

    /**
     * The HelpBroker is the default presentation of a HelpSet. A HelpBroker is an abstraction of
     * the presentation for a HelpSet; a straight-forward implementation is a JHelp() on the
     * HelpSet. A HelpBroker can be asked to show a given Navigational View, and can display a given
     * ID (help topic).
     */
    public HelpBroker hb_mcrew;

    /**
     * Default constructor that initializes the object that holds the data, adds pop-up menu, loads
     * tooltips file, adds help to the application, etc.
     */
    public TablePanel() {
        super(); //call to super mcrew_b  
        ManageData data = new ManageData();
        data.addTableDataListener(this);

        table = new Table(this, data);
        JTF_rotYears.setText(Integer.toString(data.getRotationYears()));
        standaloneFlg = true;
        addPopupMenu();
        /*
         mcrew.configFrame = new ConfigFrame(mcrew.columnConfig);
         */
        Util.loadToolTips((Container) this, new TFile("mcrew_cfg", "mcrewtooltips.cfg"));
    }


    /**
     * Single argument constructor that initializes the object that holds the data, adds pop-up
     * menu, loads tooltips file, adds help to the application, etc. Also puts the title for the
     * aplication.
     *
     * @param fileName The .MAN or .XML file from which the the data needs to be pulled in the
     * application.
     * @param cd
     */
    public TablePanel(String fileName, usda.weru.util.ConfigData cd) {
        // create an instance of mcrew
        super();

        //Awful hack to prevent the null source error from a stray MouseEvent while starting.
        /*try {
         Thread.sleep(100);
         }
         catch (InterruptedException ex) {
         }*/
        //Set the coordinator.getProjectPath() value to projDir. If MCREW is called with NO management file
        //[i.e. fileName==null] this will serve as the current directory path for the file choosers - by Neha
        //fileName = mcrewConfigFile;
        //System.out.println("Mcrew called from WEPS with filename: "+ fileName);
        //change the file Name displayed
        changeRotFileName(fileName);

        TFile filedir = new TFile(fileName);
        absFileName = filedir.getAbsolutePath();
        //System.out.println("Mcrew:Mcrew():absFilename:"+absFileName);
        /* ConfigData holds all static data such as data from
         * dataconfig.xml and all Meta data
         */
        //ConfigData.initialize("weps_mcrew_cfg");
        // Changed by Neha - The Mcrew Config file is not hard-coded.
        // Instead we can set it in the Configuration screen.
        MCREWConfig.initialize(cd);
        //If the mcrew_cfg directory is not found, then return to weps.
        if (MCREWConfig.getReturnFlag() == true) {
            LOGGER.warn("Mcrew Data Config File Not Found.");
            JOptionPane.showMessageDialog(null, "Mcrew Data Config File Not Found." + "\nPlease load the mcrew_cfg Directory",
                    "Warning", JOptionPane.WARNING_MESSAGE);
            c_labelState = true;
            return;
        }
        ManageData data = new ManageData();
        data.readDataFile(absFileName);
        // here we create the table
        table = new Table(this, data);
        table.setVisible(false);
        table.setLocation(0, 0);
        
        JTF_rotYears.setText(Integer.toString(data.getRotationYears()));
        standaloneFlg = true;
        addPopupMenu();
        /*
         mcrew.configFrame = new ConfigFrame(mcrew.columnConfig);
         */
        Util.loadToolTips((Container) this, new TFile("mcrew_cfg", "mcrewtooltips.cfg"));

        Dimension mdem = getSize();
        table.setSize(mdem.width - 20, mdem.height - 70);
        addToMain(table);
        this.setMinimumSize(new Dimension(table.getWidth(), table.getHeight()));

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                setVisible(true);
            }

        });

        c_cmis = new HashMap<String, JCheckBoxMenuItem>();
        c_tbs = new HashMap<String, JToggleButton>();

        //Setup the views defined for the table.
        
        //Init to the default
        table.toggleTableView("default", true);
        table.setVisible(true);

        calibIcon = MCREWConfig.getInitCalibColumnState();
        //here we create the instance of notes.
        notes = new NotesMan("Management File Notes", table.getData(), this);

        if ((fileName == null) || (fileName.length() == 0)) {
            return;
        }
        de.schlichtherle.truezip.file.TFile selectedFile = new TFile(fileName);
        if (selectedFile.exists()) {
            try {
                String fileDir = selectedFile.getCanonicalPath();
                //System.out.println("Mcrew:Mcrew() " + " project Dir = " + coordinator.getProjectPath());
                openFile(fileDir); // call open file method here
                table.checkData();
                //dataChanged = true;
            } catch (IOException e) {
                System.err.println("Error in opening file " + fileName);
            }
        }
        if ((coordinator.getProjectPath() == null) || (coordinator.getProjectPath().length() == 0)) {
            /* Disable Open copy of Template and Save as Template menu options	 */
            coordinator.disableOpenButtons();
            //SaveAsTJMI.setEnabled(false);
        }
        if(!table.getData().IntView()) changeTableLabel(rotMode);
        else changeTableLabel(intMode);
    }
    
    public void addToMain(Component table)
    {
        JP_main.add(table);
        javax.swing.GroupLayout timePanelLayout = new javax.swing.GroupLayout(JP_main);
        JP_main.setLayout(timePanelLayout);
        timePanelLayout.setHorizontalGroup(
            timePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(table).addGap(10, 10, Short.MAX_VALUE)
        );
        timePanelLayout.setVerticalGroup(
            timePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(table).addGap(10, 10, Short.MAX_VALUE)
        );
    }
    
    public TablePanel(ManageData data, ConfigData cd, MCREWWindow mcrew)
    {
        // create an instance of mcrew
        super();
        coordinator = mcrew;
        fileName = data.manFile != null ? data.manFile.getName() : TablePanel.sUntitledFileName;
        ManageData dataTemp = new ManageData();
        dataTemp.addTableDataListener(this);

        table = new Table(this, dataTemp);
        JTF_rotYears.setText(Integer.toString(dataTemp.getRotationYears()));
        /*
         mcrew.configFrame = new ConfigFrame(mcrew.columnConfig);
         */
        Util.loadToolTips((Container) this, new TFile("mcrew_cfg", "mcrewtooltips.cfg"));

        //Awful hack to prevent the null source error from a stray MouseEvent while starting.
        /*try {
         Thread.sleep(100);
         }
         catch (InterruptedException ex) {
         }*/
        //Set the coordinator.getProjectPath() value to projDir. If MCREW is called with NO management file
        //[i.e. fileName==null] this will serve as the current directory path for the file choosers - by Neha
        //fileName = mcrewConfigFile;
        //System.out.println("Mcrew called from WEPS with filename: "+ fileName);
        //change the file Name displayed
        changeRotFileName(fileName);

        TFile filedir = new TFile(fileName);
        absFileName = filedir.getAbsolutePath();
        //System.out.println("Mcrew:Mcrew():absFilename:"+absFileName);
        /* ConfigData holds all static data such as data from
         * dataconfig.xml and all Meta data
         */
        //ConfigData.initialize("weps_mcrew_cfg");
        // Changed by Neha - The Mcrew Config file is not hard-coded.
        // Instead we can set it in the Configuration screen.
        //If the mcrew_cfg directory is not found, then return to weps.
        if (MCREWConfig.getReturnFlag() == true) {
            LOGGER.warn("Mcrew Data Config File Not Found.");
            JOptionPane.showMessageDialog(null, "Mcrew Data Config File Not Found." + "\nPlease load the mcrew_cfg Directory",
                    "Warning", JOptionPane.WARNING_MESSAGE);
            c_labelState = true;
            return;
        }
        // here we create the table
        table = new Table(this, data);
        table.setVisible(false);
        table.setLocation(0, 0);
        
        JTF_rotYears.setText(Integer.toString(data.getRotationYears()));
        standaloneFlg = true;
        addPopupMenu();
        /*
         mcrew.configFrame = new ConfigFrame(mcrew.columnConfig);
         */
        Util.loadToolTips((Container) this, new TFile("mcrew_cfg", "mcrewtooltips.cfg"));

        Dimension mdem = getSize();
        table.setSize(mdem.width - 20, mdem.height - 70);
        addToMain(table);
        this.setMinimumSize(new Dimension(table.getWidth(), table.getHeight()));

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                setVisible(true);
            }

        });

        c_cmis = new HashMap<String, JCheckBoxMenuItem>();
        c_tbs = new HashMap<String, JToggleButton>();

        //Setup the views defined for the table.
        
        //Init to the default
        table.toggleTableView("default", true);
        table.setVisible(true);

        calibIcon = MCREWConfig.getInitCalibColumnState();
        //here we create the instance of notes.
        notes = new NotesMan("Management File Notes", table.getData(), this);

        if ((fileName == null) || (fileName.length() == 0)) {
            return;
        }
        de.schlichtherle.truezip.file.TFile selectedFile = new TFile(fileName);
        if (selectedFile.exists()) {
            try {
                String fileDir = selectedFile.getCanonicalPath();
                //System.out.println("Mcrew:Mcrew() " + " project Dir = " + coordinator.getProjectPath());
                openFile(fileDir); // call open file method here
                table.checkData();
                //dataChanged = true;
            } catch (IOException e) {
                System.err.println("Error in opening file " + fileName);
            }
        }
        if ((coordinator.getProjectPath() == null) || (coordinator.getProjectPath().length() == 0)) {
            /* Disable Open copy of Template and Save as Template menu options	 */
            coordinator.disableOpenButtons();
            //SaveAsTJMI.setEnabled(false);
        }
    }
    
    /**
     * Adds the specified view JCheckBoxMenuItem.
     * @param name
     * @param item 
     */
    public void addCmis(String name, JCheckBoxMenuItem item) { c_cmis.put(name, item); }
    /**
     * Returns the checkbox associated with the name.
     * @param name
     * @return 
     */
    public JCheckBoxMenuItem getCmis(String name) { return c_cmis.get(name); }
    /**
     * Adds the specified view Togglebutton.
     * @param name
     * @param item 
     */
    public void addTbs(String name, JToggleButton item) { c_tbs.put(name, item); }
    /**
     * Returns the specified view Togglebutton associated with the name.
     * @param name
     * @return 
     */
    public JToggleButton getTbs(String name) { return c_tbs.get(name); }
    /**
     * Adds the specified togglebutton to the toolbar.
     * @param tb 
     */
    public void addtoToolbar(JToggleButton tb) { JTB_view.add(tb); }
    
    private Map<String, JCheckBoxMenuItem> c_cmis;
    private Map<String, JToggleButton> c_tbs;

    public void handleViewToggle(String name, boolean state) {
        JCheckBoxMenuItem cmi = c_cmis.get(name);
        JToggleButton tb = c_tbs.get(name);

        table.toggleTableView(name, state);

        if (cmi != null) {
            cmi.setSelected(state);
        }

        if (tb != null) {
            tb.setSelected(state);
        }
        this.setPreferredSize(new Dimension(table.getWidth(), table.getHeight()));
    }
    
    @Override
    protected void rotIntToggle(ActionEvent evt)
    {
        if(table.getData().IntView()) coordinator.JMI_ItR_ActionPerformed(evt);
        else coordinator.JMI_RtI_ActionPerformed(evt);
    }

    /**
     *
     * @return
     */
    public boolean getLabelState() {
        return c_labelState;
    }
    
    public MCREWWindow getCoordinator() { return coordinator; }
    
    public void commitEdit() { if(table != null) table.commitEdit(); } 
    
    public void setRotText(String input)
    {
        try { Integer.parseInt(input); }
        catch(NumberFormatException nfe) { return; } 
        JTF_rotYears.setText(input);
        table.checkWrap();
    }

    /**
     * In case running a standalone version of the application, this becomes the starting point of
     * the application.
     *
     * @param args A command line array of arguments such as fille name, screen title, etc.
     */
    public static void main(String[] args) {
        System.setProperty("line.separator", "\n"); // make file line separator unix compatible
        // create an instance of mcrew
        JFrame fram = new JFrame();
        TablePanel mp = new TablePanel();

        mp.standaloneFlg = true;

        //ConfigData holds all static data such as data from
        //mcrewconfig.xmland all Meta data
        MCREWConfig.initialize(ConfigData.getDefault());
                
//        TimelinePanel time = new TimelinePanel(args);
//        TimelineControls controls = new TimelineControls(time);
//        time.linkControls(controls);
//        ComboTimeline panel = new ComboTimeline(time, controls);
//        
//        ManageData data= panel.timeline.getManageData(0);
//        panel.setLocation(0, 0);
//
//        // here we create the table
//        mp.table = new Table(data);
//        fram.add(mp);
//        mp.table.setLocation(0, 0);
//
//        Dimension mdem = mp.getSize();
//        mp.setSize(mdem.width - 20, mdem.height - 70);
////        mdem = mp.timelineContainer.getSize();
//        panel.setSize(mdem.width - 20, mdem.height - 20);
//        mp.JP_main.add(mp.table);
////        mp.timelineAndControls.add(panel);
//        mp.setVisible(true);
//        fram.setVisible(true);
//        temp.repaint();

        /* Disable Open copy of Template and Save as Template menu options when running standalone */
//        mp.JMI_openCT.setEnabled(false);
        //mp.SaveAsTJMI.setEnabled(false);
        //When running stand-alone,the return arrow should not be displayed
//        mp.JB_close.setVisible(false);
    }
    private javax.swing.JMenuItem popCutJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popCopyJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popPasteJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popDeleteJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popUndoDeleteJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popInsertJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popInsertOperationJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popInsertFileJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popInsertFileDateAdjustedJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popAddRotationDateAdjustedJMI = new javax.swing.JMenuItem();

    private javax.swing.JMenuItem popDrillDownScreenJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popAdjustDateJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem popSetDateJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem setDateJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem calendarDateJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem dateChangeDateJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem dateIncrementYearJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem dateDecrementYearJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem dateIncrementMonthJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem dateDecrementMonthJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem dateIncrementWeekJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem dateDecrementWeekJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem dateIncrementDayJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem dateDecrementDayJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem operationScreenJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem operationNotesJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem addChangeOperationJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem cropScreenJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem addChangeCropJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem cropNotesJMI = new javax.swing.JMenuItem();
    // Menu items for popup for "Tillage direction" cells
    private javax.swing.JMenuItem setDirectionJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem adjustDirectionJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem setTozeroJMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem setTo45JMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem setTo90JMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem incrementBy15JMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem decrementBy15JMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem incrementBy45JMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem decrementBy45JMI = new javax.swing.JMenuItem();
    private javax.swing.JMenuItem changeBy90JMI = new javax.swing.JMenuItem();

    /**
     *
     * @param cursor
     */
    @Override
    public void setCursor(Cursor cursor) {
        super.setCursor(cursor);
        Table temp = table;
        if (temp != null) {
            temp.setCursor(cursor);
        }
    }

    /**
     *
     * @param wait
     */
    public void setWaiting(boolean wait) {
        if (wait) {
            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        } else {
            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
    }

    private void addPopupMenu() {
        MenuElement[] menuElements;

        popup = new JPopupMenu();
        datePopup = new JPopupMenu();
        // operationPopup = new JPopupMenu();
        // cropPopup = new JPopupMenu();
        operationCellPopup = new JPopupMenu();
        cropCellPopup = new JPopupMenu();
        tillageCellPopup = new JPopupMenu();

        popupVec = new Vector<MenuElement>();
        datePopupVec = new Vector<MenuElement>();
        //operationPopupVec = new Vector();
        //cropPopupVec = new Vector();
        operationCellPopupVec = new Vector<MenuElement>();
        cropCellPopupVec = new Vector<MenuElement>();
        tillageCellPopupVec = new Vector<MenuElement>();

        SymAction lSymAction = new SymAction();

        popSetDateJMI.setText("Set Date");
        popSetDateJMI.setActionCommand("Set Date");
        popSetDateJMI.addActionListener(lSymAction);
        popup.add(popSetDateJMI);

        popAdjustDateJMI.setText("Adjust Date");
        popAdjustDateJMI.setActionCommand("Adjust Date");
        popAdjustDateJMI.addActionListener(lSymAction);
        popup.add(popAdjustDateJMI);

        popInsertJMI.setText("Insert Blank Row");
        popInsertJMI.setActionCommand("Insert Blank Row");
        popInsertJMI.addActionListener(lSymAction);
        popup.add(popInsertJMI);

        popInsertOperationJMI.setText("Insert Operation");
        popInsertOperationJMI.setActionCommand("Insert Operation");
        popInsertOperationJMI.addActionListener(lSymAction);
        popup.add(popInsertOperationJMI);

        popAddRotationDateAdjustedJMI.setText("Insert Rotation");
        popAddRotationDateAdjustedJMI.setActionCommand("Add Rotation");
        popAddRotationDateAdjustedJMI.addActionListener(lSymAction);
        popup.add(popAddRotationDateAdjustedJMI);

        popInsertFileDateAdjustedJMI.setText("Insert Management");
        popInsertFileDateAdjustedJMI.setActionCommand("Insert File");
        popInsertFileDateAdjustedJMI.addActionListener(lSymAction);
        popup.add(popInsertFileDateAdjustedJMI);

        //only show if not in Interval view
        if (!usda.weru.util.ConfigData.getDefault().isCompatibilityNRCS()) {
            popInsertFileJMI.setText("Insert Management (Unadjusted)");
            popInsertFileJMI.setActionCommand("Insert File (Unadjusted)");
            popInsertFileJMI.addActionListener(lSymAction);

            popup.add(popInsertFileJMI);
        }

        // Now follws multiple row operations
        popCutJMI.setText("Cut Row(s)");
        popCutJMI.setActionCommand("Cut ");
        popCutJMI.addActionListener(lSymAction);
        popup.add(popCutJMI);

        popCopyJMI.setText("Copy Row(s)");
        popCopyJMI.setActionCommand("Copy");
        popCopyJMI.addActionListener(lSymAction);
        popup.add(popCopyJMI);

        popPasteJMI.setText("Paste Row(s)");
        popPasteJMI.setActionCommand("Paste");
        popPasteJMI.addActionListener(lSymAction);
        popup.add(popPasteJMI);

        popDeleteJMI.setText("Delete Row(s)");
        popDeleteJMI.setActionCommand("Delete");
        popDeleteJMI.addActionListener(lSymAction);
        popup.add(popDeleteJMI);

        popUndoDeleteJMI.setText("Undo Delete Row(s)");
        popUndoDeleteJMI.setActionCommand("Undo Ddelete");
        popUndoDeleteJMI.addActionListener(lSymAction);
        popup.add(popUndoDeleteJMI);
        setUndoDeleteStatus(false);

        menuElements = popup.getSubElements();
        popupVec.addAll(Arrays.asList(menuElements));

        /* date popup menu optipns */
        calendarDateJMI.setText("Calendar Date");
        calendarDateJMI.setActionCommand("Calender Date");
        calendarDateJMI.addActionListener(lSymAction);
        datePopup.add(calendarDateJMI);

        setDateJMI.setText("Set Date");
        setDateJMI.setActionCommand("Set Date");
        setDateJMI.addActionListener(lSymAction);
        datePopup.add(setDateJMI);

        dateChangeDateJMI.setText("Adjust Date");
        dateChangeDateJMI.setActionCommand("Change Date");
        dateChangeDateJMI.addActionListener(lSymAction);
        datePopup.add(dateChangeDateJMI);

        dateIncrementYearJMI.setText("Increment Year");
        dateIncrementYearJMI.setActionCommand("Increment Year");
        dateIncrementYearJMI.addActionListener(lSymAction);
        datePopup.add(dateIncrementYearJMI);

        dateDecrementYearJMI.setText("Decrement Year");
        dateDecrementYearJMI.setActionCommand("Decrement Year");
        dateDecrementYearJMI.addActionListener(lSymAction);
        datePopup.add(dateDecrementYearJMI);

        dateIncrementMonthJMI.setText("Increment Month");
        dateIncrementMonthJMI.setActionCommand("Increment Month");
        dateIncrementMonthJMI.addActionListener(lSymAction);
        datePopup.add(dateIncrementMonthJMI);

        dateDecrementMonthJMI.setText("Decrement Month");
        dateDecrementMonthJMI.setActionCommand("Decrement Month");
        dateDecrementMonthJMI.addActionListener(lSymAction);
        datePopup.add(dateDecrementMonthJMI);

        dateIncrementWeekJMI.setText("Increment by week");
        dateIncrementWeekJMI.setActionCommand("Increment by week");
        dateIncrementWeekJMI.addActionListener(lSymAction);
        datePopup.add(dateIncrementWeekJMI);

        dateDecrementWeekJMI.setText("Decrement by week");
        dateDecrementWeekJMI.setActionCommand("Decrement by week");
        dateDecrementWeekJMI.addActionListener(lSymAction);
        datePopup.add(dateDecrementWeekJMI);

        dateIncrementDayJMI.setText("Increment Day");
        dateIncrementDayJMI.setActionCommand("Increment Day");
        dateIncrementDayJMI.addActionListener(lSymAction);
        datePopup.add(dateIncrementDayJMI);

        dateDecrementDayJMI.setText("Decrement Day");
        dateDecrementDayJMI.setActionCommand("Decrement Day");
        dateDecrementDayJMI.addActionListener(lSymAction);
        datePopup.add(dateDecrementDayJMI);

        menuElements = datePopup.getSubElements();
        datePopupVec.addAll(Arrays.asList(menuElements));

        /* operation and crop cell popup menu items */
        addChangeOperationJMI.setText("Change/Select Operation");
        addChangeOperationJMI.setActionCommand("Add/Change Operation");
        addChangeOperationJMI.addActionListener(lSymAction);
        operationCellPopup.add(addChangeOperationJMI);

        operationScreenJMI.setText("Operation Drill-down Screen");
        operationScreenJMI.setActionCommand("Operation Drill-down Screen");
        operationScreenJMI.addActionListener(lSymAction);
        operationCellPopup.add(operationScreenJMI);
        
        operationNotesJMI.setText("View Operation Notes");
        operationNotesJMI.setActionCommand("View Operation Notes");
        operationNotesJMI.addActionListener(lSymAction);
        operationCellPopup.add(operationNotesJMI);

        menuElements = operationCellPopup.getSubElements();
        operationCellPopupVec.addAll(Arrays.asList(menuElements));

        addChangeCropJMI.setText("Change/Select Crop");
        addChangeCropJMI.setActionCommand("Add/Change Crop");
        addChangeCropJMI.addActionListener(lSymAction);
        cropCellPopup.add(addChangeCropJMI);

        cropScreenJMI.setText("Crop Drill-down Screen");
        cropScreenJMI.setActionCommand("Crop Drill-down Screen");
        cropScreenJMI.addActionListener(lSymAction);
        cropCellPopup.add(cropScreenJMI);
        
        cropNotesJMI.setText("View Crop/Residue Notes");
        cropNotesJMI.setActionCommand("View Crop/Residue Notes");
        cropNotesJMI.addActionListener(lSymAction);
        cropCellPopup.add(cropNotesJMI);

        menuElements = cropCellPopup.getSubElements();
        cropCellPopupVec.addAll(Arrays.asList(menuElements));

        //datePopup.setText("Date functions");
        //popup.add(datePopup);
        /* Tillage Direction popup menu items - neha */
        setDirectionJMI.setText("Set Direction");
        setDirectionJMI.setActionCommand("Set Direction");
        setDirectionJMI.addActionListener(lSymAction);
        tillageCellPopup.add(setDirectionJMI);

        adjustDirectionJMI.setText("Adjust Direction");
        adjustDirectionJMI.setActionCommand("Adjust Direction");
        adjustDirectionJMI.addActionListener(lSymAction);
        tillageCellPopup.add(adjustDirectionJMI);

        setTozeroJMI.setText("Set to 0 deg");
        setTozeroJMI.setActionCommand("Set to 0 deg");
        setTozeroJMI.addActionListener(lSymAction);
        tillageCellPopup.add(setTozeroJMI);

        setTo45JMI.setText("Set to 45 deg");
        setTo45JMI.setActionCommand("Set to 45 deg");
        setTo45JMI.addActionListener(lSymAction);
        tillageCellPopup.add(setTo45JMI);

        setTo90JMI.setText("Set to 90 deg");
        setTo90JMI.setActionCommand("Set to 90 deg");
        setTo90JMI.addActionListener(lSymAction);
        tillageCellPopup.add(setTo90JMI);

        incrementBy15JMI.setText("Increment 15 deg");
        incrementBy15JMI.setActionCommand("Increment 15 deg");
        incrementBy15JMI.addActionListener(lSymAction);
        tillageCellPopup.add(incrementBy15JMI);

        decrementBy15JMI.setText("Decrement 15 deg");
        decrementBy15JMI.setActionCommand("Decrement 15 deg");
        decrementBy15JMI.addActionListener(lSymAction);
        tillageCellPopup.add(decrementBy15JMI);

        incrementBy45JMI.setText("Increment 45 deg");
        incrementBy45JMI.setActionCommand("Increment 45 deg");
        incrementBy45JMI.addActionListener(lSymAction);
        tillageCellPopup.add(incrementBy45JMI);

        decrementBy45JMI.setText("Decrement 45 deg");
        decrementBy45JMI.setActionCommand("Decrement 45 deg");
        decrementBy45JMI.addActionListener(lSymAction);
        tillageCellPopup.add(decrementBy45JMI);

        changeBy90JMI.setText("Change by 90 deg");
        changeBy90JMI.setActionCommand("Change by 90 deg");
        changeBy90JMI.addActionListener(lSymAction);
        tillageCellPopup.add(changeBy90JMI);

        menuElements = tillageCellPopup.getSubElements();
        tillageCellPopupVec.addAll(Arrays.asList(menuElements));

        popupListener = new PopupListener();
        this.addMouseListener(popupListener);
    }

    /**
     * This method sets the rotaion year in the frame from the management data Changes the Rotation
     * File Name displayed and adjusts the scroll bar accordingly
     *
     * @param fileName The new filename to be used.
     */
    public void changeRotFileName(String fileName) {
        filePathName = fileName;
        updateRotFileName();
        changes.firePropertyChange(RunFileData.ManageFile, null, new TFile(fileName).getPath());
    }

    /**
     *
     */
    public void updateRotFileName() {
        String text = "";
        if (table.getDataChanged()) {
            text = filePathName + "  (Modified)";
            JL_rotation2.setForeground(Color.BLUE);
        } else {
            text = filePathName;
            JL_rotation2.setForeground(Color.BLACK);
        }
        JL_rotation2.setText(text);
    }

    /**
     *
     * @param changed
     */
    public void setDataChanged(boolean changed) {
        if(table.getDataChanged() ^ changed) coordinator.dataChange(changed);
        table.setDataChanged(changed);

        //Cheating, but we only allow one mcrew open at a time.
        if (MCREWWindow.openMcrewWindows.isEmpty()) {
            return;
        }
        updateRotFileName();
    }

    /**
     * This method sends the new rotation year to the data
     *
     * @param yrs The new year to be set.
     */
    public void changeRotYears(String yrs) {
        //local cache to try and work around rare threading issues
        ManageData temp = table.getData();
        if (temp == null) {
            return;
        }
        try {
            int old = temp.getRotationYears();
            int years = new Integer(yrs);
            if (years != old) {
                temp.setRotationYears(years);
                setDataChanged(true);
            }
        } catch (NumberFormatException e) {
            LOGGER.error("Mcrew:changeRotYears()->" + "Please enter a number for RotationYears");
            JTF_rotYears.setText(Integer.toString(temp.getRotationYears()));
            table.checkWrap();
        } catch (NullPointerException npe) {
            LOGGER.debug("Null Data Object", npe);
        }

    }

    @Override
    public void RotYearsJT_focusLost(java.awt.event.FocusEvent event) {
        ////System.out.println("RotYearsJT focuslost" + RotYearsJT.getText());
        changeRotYears(JTF_rotYears.getText());
    }

    @Override
    public void RotYearsJT_actionPerformed(java.awt.event.ActionEvent event) {
        ////System.out.println("RotYearsJT actionperformed - "+ RotYearsJT.getText());
        changeRotYears(JTF_rotYears.getText());
    }

    /**
     * This function opens an existing management file and sets the rotation text box
     *
     * @param fullPathName The path where this file reisdes in the system or on the network.
     */
    public void openFile(String fullPathName) throws IllegalStateException {
        boolean resort = table.getData().IntView();
        if(resort) 
        {
            try { this.table.getData().inttoRotSort(); }
            catch(Exception e) 
            {
                table.getData().setRotationYears(table.getData().kRotationYears + 100);
                try { this.table.getData().inttoRotSort(); }
                catch(Exception ex) {}
            }
            
        }
        setWaiting(true);
        try {
            //System.out.println("Mcrew: openFile: Opening the file " + fullPathName);
            if (fullPathName.equals("")) {
                System.err.println("File not selected error");
                return;
            }

            //data.readDataFile(fullPathName);
            /* Read data on a new ManageData object and assign it to 'data'only on success
             'data' is the ManageData object associated with the 'table'[Table object],
             'table' in associated with this Mcrew object. */
            ManageData newData = new ManageData();
            int dataReadValue = newData.readDataFile(fullPathName);
            //System.out.println("Mcrew:openfile" + "  datareadvalue = " +dataReadValue);
            switch (dataReadValue) {
                case ManageData.kCorruptedFile:
                    JOptionPane.showMessageDialog(this, "Unable to read management file " + fullPathName
                            + "\nThe file appears to be corrupted.", "Corrupted File", JOptionPane.ERROR_MESSAGE);
                    return;
                case ManageData.kWrong_Version:
                    String[] errorMsg = new String[2];
                    errorMsg[0] = "Management file " + fullPathName + "\nis of version " + newData.version
                            + ", whereas the current version is " + ManageData.VERSION_MINIMUM + ".";

                    errorMsg[1] = "Do you want to continue reading ?";

                    int reply = JOptionPane.showConfirmDialog(this, errorMsg, "Version", JOptionPane.YES_NO_OPTION,
                            JOptionPane.QUESTION_MESSAGE);
                    if (reply == JOptionPane.NO_OPTION) {
                        return;
                    }
                    break;
                case ManageData.kFile_NotFound:
                    System.err.println("Mcrew:openFile() " + "Cannot find the file. Strange!!");
                    return;
                case ManageData.kUnknown_Error:
                    System.err.println("Mcrew:openFile() " + "Unknown error reading data file");
                    return;
                case ManageData.kSuccess:
                    //System.out.println("Data read succesfully");
                    break;
                default:
                    break;
            }

            //Issue: 543, there is a chance of threading race condition.  So we wait to make sure the data is not null.
            while (table.getData() == null) {
                Thread.yield();
            }
            table.getData().readDataFile(fullPathName);
            table.checkData();

            TFile file = new TFile(fullPathName);
            fileName = file.getName();
            savePath = file.getParent();

            //Set the Text Field to the absolute path of current opened file.
            try {
                filePathName = file.getCanonicalPath();
                changeRotFileName(filePathName);
                //RotationJT.setText(filePathName);
            } catch (IOException e) {
                LOGGER.error("Unable to read file: " + file.getAbsolutePath(), e);
            }

            JTF_rotYears.setText(Integer.toString(table.getData().getRotationYears()));
            table.checkWrap();
        } finally {
            setWaiting(false);
        }

        if(resort)
        {
            table.getData().rotToIntSort();
        }
        setDataChanged(false);
        table.checkAllConditions();
        refreshMcrewTableData();
    }
    
    /**
     * This function resets the table and the current manage data to a new file.
     */
    public void newFile()
    {
        table.getData().setWepsManFileNotes("");
        fileName = sUntitledFileName;
        //RotationJT.setText(fileName);
        changeRotFileName(fileName);
        table.getData().clear();
        notes.JTA_Notes.setText("");
        JTF_rotYears.setText(Integer.toString(table.getData().getRotationYears()));
        setDataChanged(false);

        invalidate();
        repaint();
    }

    /**
     * This method lets you open an updated file when a file data is modified and saved and the new
     * data needs to be displayed.
     *
     * @param fullPathName The system or network path where this file resides.
     */
    public void openRefreshedFile(String fullPathName) {
        setWaiting(true);
        try {
            table.getData().readDataFile(fullPathName);
            table.checkData();
            TFile file = new TFile(fullPathName);
            fileName = file.getName();
            savePath = file.getParent();

            //Set the Text Field to the absolute path of current opened file.
            try {
                filePathName = file.getCanonicalPath();
                changeRotFileName(filePathName);
            } catch (IOException e) {
                LOGGER.error("Error reading file: " + file.getAbsolutePath(), e);
            }

            JTF_rotYears.setText(Integer.toString(table.getData().getRotationYears()));
            //System.out.println("Mcrew:openFile->" + "Rotation years: " + data.getRotationYears());
        } finally {
            setWaiting(false);
        }
        setDataChanged(false);
        table.checkAllConditions();

    }

    /**
     *
     */
    public void cleanup() {
        try {
            MCREWConfig.cleanup();

            Table tempTable = table;
            if (tempTable != null) {
                tempTable.cleanup();
            }
        } catch (Exception e) {
            LOGGER.warn("Unable to clean up mcrew data structures.", e);
        }

    }

    /**
     *
     * @param enabled
     */
    public void setUndoDeleteStatus(boolean enabled) {
        enabled = table.getData() != null && table.getData().deletedRows != null && table.getData().deletedRows.size() > 0;
        coordinator.setUndoDeleteStatus(enabled);
        popUndoDeleteJMI.setEnabled(enabled);
    }

    /**
     *
     */
    public void setDeleted() {
        setUndoDeleteStatus(true);
    }

    // here we map the tool bar buttons to the menu items
    @Override
    public void OpenJB_actionPerformed(java.awt.event.ActionEvent event) {
        setUndoDeleteStatus(false);
        coordinator.existingOverwrite();
    }

    @Override
    protected void NewJB_actionPerformed(java.awt.event.ActionEvent event) {
        setUndoDeleteStatus(false);
        coordinator.newOverwrite();
    }

    @Override
    protected void SaveJB_actionPerformed(java.awt.event.ActionEvent event) {
        setUndoDeleteStatus(false);
        saveCurrent();
    }
    
    @Override
    public void CycFwdJB_actionPerformed(java.awt.event.ActionEvent evt) {
        coordinator.CycleFwdJMI_actionPerformed(evt);
    }
    
    @Override
    public void CycBwdJB_actionPerformed(java.awt.event.ActionEvent evt) {
        coordinator.CycleBwdJMI_actionPerformed(evt);
    }

    @Override
    protected void CutJB_actionPerformed(java.awt.event.ActionEvent event) {
        setUndoDeleteStatus(false);
        CutJMI_actionPerformed(event);
    }

    @Override
    protected void CopyJB_actionPerformed(java.awt.event.ActionEvent event) {
        setUndoDeleteStatus(false);
        CopyJMI_actionPerformed(event);
    }

    //CancelButton_actionPerformed(java.awt.event.ActionEvent evt)
    @Override
    protected void PasteJB_actionPerformed(java.awt.event.ActionEvent event) {
        setUndoDeleteStatus(false);
        PasteJMI_actionPerformed(event);
    }

    @Override
    protected void SortJB_actionPerformed(java.awt.event.ActionEvent event) {
        setUndoDeleteStatus(false);
        SortJMI_actionPerformed(event);
    }

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

        NotesJMI_actionPerformed(evt);
    }
    /**
     * This method knows what to do when state change occurs for a particular object or item.
     *
     * @param e The state change that occured for a particular item.
     */
    @Override
    public void itemStateChanged(ItemEvent e) {
    }

    /**
     * The action to be taken based on the event that happens.
     *
     * @param e The event that is to be recognised for action to be performed.
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        //System.out.println("MCrew: actionPerformed: name = " + e);
    }


    private boolean checked = false;

    /**
     * If refreshmcrewscreen is true, we try to open the saved data .MAN/.XML to load the most
     * recent data onto the main MCREW screen table.
     */
    public void refreshMcrewTableData() {

        //System.out.println("Mcrew: refreshMcrewTableData : Saving file");
        if ((fileName == null) || (fileName.length() == 0) || (fileName.equals(sUntitledFileName))) {
            ////System.out.println("Calling save as with fileName " + fileName);
            //SaveAsJMI_actionPerformed(event);
            return;
        }
        if (!checked) {
            if (table.checkAllConditions() == false) {
                saveSuccess = false;
                return; // user pressed cancel on some option, Don't save
            }
        }

        //If the use doesnt opens a file or opens a tamplate of a file
        // and wothout making any changes saves the file, then the "absFileName"
        // should reflect this saved file.
        absFileName = filePathName;

        if (table != null && table.getDataChanged() == false) {
            return;
        }
        if ((savePath == null) || (savePath.length() == 0)) {
            savePath = MCREWConfig.getDirectoryName(XMLConstants.smanagement_template);

            ////System.out.println("Data changed " + dataChanged);
        }
        String fullPathFileName = savePath + TFile.separator + fileName;
        //System.out.println("MCREW : refreshMcrewTableData : Saving file " + fullPathFileName);
        //Get the parent location of this file, see if its writable,if not
        //display the warning message and return.-by Neha
        TFile mcrewFile = new TFile(fullPathFileName);
        TFile parentFile = new TFile(mcrewFile.getParentFile());
        //System.out.println("MCREW : refreshMcrewTableData : parent file"+mcrewFile.getParent()
        //+" can we write into this location:"+parentFile.canWrite());
        if (parentFile.canWrite() == false) {
            JOptionPane.showMessageDialog(this, "The File location Specified is not writable\n "
                    + fullPathFileName, "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }

        table.getData().writeDataFile(savePath + TFile.separator + fileName);
        //update the abs file path name to this path of the saved file
        absFileName = fullPathFileName;

        setDataChanged(false);
        saveSuccess = true;

        if (refreshMcrewScreen.equals("true")) {
            openRefreshedFile(absFileName);
            refreshMcrewScreen = "false";
        }

        //System.out.println("Returning after saving file");
    }
    private PropertyChangeSupport changes = new PropertyChangeSupport(this);

    /**
     * Add a PropertyChangeListener to the listener list. The listener is registered for all
     * properties
     *
     * @param l PropertyChangeListener to be added
     */
    @Override
    public void addPropertyChangeListener(PropertyChangeListener l) {
        changes.addPropertyChangeListener(l);
    }

    /**
     * Remove a PropertyChangeListener from the listener list. This removes a PropertyChangeListener
     * that was registered for all properties.
     *
     * @param l The PropertyChangeListener to be removed
     */
    @Override
    public void removePropertyChangeListener(PropertyChangeListener l) {
        changes.removePropertyChangeListener(l);
    }

   

    /* This code is for the pop-up menu
     */
    class PopupListener extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            ////System.out.println("Mcrew: mousepressed:");
            maybeShowPopup(e);
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            ////System.out.println("Mcrew: released:");
            maybeShowPopup(e);
        }

        private void maybeShowPopup(MouseEvent e) {
            if (e.isPopupTrigger()) {
                e.consume();
                popup.show(e.getComponent(), e.getX(), e.getY());
            }
        }
    }

   public void addCSH(HelpSet hs_mcrew) {
        hb_mcrew = hs_mcrew.createHelpBroker();
        //hb_mcrew = hs_mcrew.getHelpBroker();
        hb_mcrew.enableHelpKey(getRootPane(), "McrewIntro_html", hs_mcrew);
        ActionListener helper = new CSH.DisplayHelpFromSource(hb_mcrew);
        CSH.setHelpIDString(JTB_main, "mcrewButtonBar_html");
        CSH.setHelpIDString(JB_new, "mcrewNewButton_html");
        CSH.setHelpIDString(JB_open, "mcrewOpenButton_html");
        CSH.setHelpIDString(JB_save, "mcrewSaveButton_html");
        CSH.setHelpIDString(JB_cut, "mcrewCutButton_html");
        CSH.setHelpIDString(JB_copy, "mcrewCopyButton_html");
        CSH.setHelpIDString(JB_paste, "mcrewPasteButton_html");
        CSH.setHelpIDString(JB_sort, "mcrewSortButton_html");
        CSH.setHelpIDString(JB_cycleFwd, "mcrewRotateFowardButton_html");
        CSH.setHelpIDString(JB_cycleBwd, "mcrewRotateBackwardButton_html");
        CSH.setHelpIDString(JB_notes, "mcrewPencilButton_html");
        CSH.setHelpIDString(JL_yrofRot, "MCREWYrRot_html");
        CSH.setHelpIDString(JTF_rotYears, "MCREWYrRot_html");
        CSH.setHelpIDString(JP_rotationFile, "MCREWRotName_html");
        CSH.setHelpIDString(JP_main, "mcrewTableview_html");
        if(c_tbs != null)
        {
            for(String item : c_tbs.keySet())
            {
                CSH.setHelpIDString(c_tbs.get(item), "mcrewYieldButton_html");
            }
        }
    } //end of addCSH

    @Override
    public void dataChanged(JCTableDataEvent e) {
        setDataChanged(true);

        //TODO: clean this up, it is really crude
        for (MCREWConfig.TableView view : MCREWConfig.getTableViews()) {
            if (view.isAuto()) {
                if (isViewRequired(view)) {
                    handleViewToggle(view.getName(), true);
                } else {
                    handleViewToggle(view.getName(), false);
                }
            }
        }
    }

    private boolean isViewRequired(MCREWConfig.TableView view) {
        for (RowInfo row : table.getData().getRows()) {
            OperationObject operation = (OperationObject) row.getDataObject("operation");
            if (operation != null) {
                for (Action action : operation.getAllActions()) {
                    for (String tagname : view.getColumnNames()) {
                        if (action.getParameterNames().contains(tagname)) {
                            return true;
                        }
                    }

                }
            }
        }
        return false;
    }

    void DrillDownScreenJMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.showDrillDownScreen();
    }

    void SetDateJMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.setDates();
    }

    void ChangeDateJMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.changeDates();
    }

    void CalendarDateJMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.calendarDates();
    }

    void SetDirectionJMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.setDirection();
    }

    void AdjustDirectionJMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.adjustDirection();
    }

    void SetToZeroJMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.setAbsoluteDirection(0);
    }

    void SetTo45JMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.setAbsoluteDirection(45);
    }

    void SetTo90JMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.setAbsoluteDirection(90);
    }

    void IncrementBy15JMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.incrDecrDir(15);
    }

    void DecrementBy15JMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.incrDecrDir(-15);
    }

    void IncrementBy45JMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.incrDecrDir(45);
    }

    void DecrementBy45JMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.incrDecrDir(-45);
    }

    void ChangeBy90JMI_actionPerformed(java.awt.event.ActionEvent event) {
        table.changeBy90();
    }
    
    void CutJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setWaiting(true);
        try {
            setUndoDeleteStatus(false);
            table.cutRows();
            table.checkData();
            setDataChanged(true);
        } finally {
            setWaiting(false);
        }
    }
    
    /**
     * This method is called when the cut option is selected ConfigData/ void
     * CutJMI_actionPerformed(java.awt.event.ActionEvent event) { // //System.out.println("Mcrew:
     * Cut Action: Cut row"); table.cutRows(); }
     *
     * /**
     * This method is called when the copy option is selected
     *
     * @param event
     */
    void CopyJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setUndoDeleteStatus(false);
        ////System.out.println("Mcrew: CopyJMI action");
        table.copyRows();
    }
    
    void PasteJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setWaiting(true);
        try {
            setUndoDeleteStatus(false);
            table.pasteRows();
            setDataChanged(true);
        } finally {
            setWaiting(false);
        }
    }
    
    void DeleteJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setWaiting(true);
        try {
            table.deleteRows();
            table.checkData();
            setUndoDeleteStatus(true);
            setDataChanged(true);
        } finally {
            setWaiting(false);
        }
    }
    
    void UndoDeleteJMI_ActionPerformed(java.awt.event.ActionEvent evt) {
        setWaiting(true);
        try {
            table.undoDeleteRows();
            table.checkData();
            setUndoDeleteStatus(false);
        } finally {
            setWaiting(false);
        }
    }
    
    void InsertOperationJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setUndoDeleteStatus(false);
        table.insertRow();
        boolean added = table.addColumnData(1);
        //Make sure a operation was added.
        if (!added) {
            table.deleteRows();
        }
    }
    
    void CycleFwdJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setWaiting(true);
        try {
            long time = System.currentTimeMillis();
            while (table.checkAndSetRotYears() == -1) {
                if (System.currentTimeMillis() - time > 5000) {
                    return;
                }
            }
            int rotYears = Integer.parseInt(JTF_rotYears.getText());
            table.cycleForward(rotYears);
        } finally {
            setWaiting(false);
        }
    }
    
    void CycleBwdJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setWaiting(true);
        try {
            long time = System.currentTimeMillis();
            while (table.checkAndSetRotYears() == -1) {
                if (System.currentTimeMillis() - time > 5000) {
                    return;
                }
            }
            int rotYears = new Integer(JTF_rotYears.getText());
            table.cycleBackward(rotYears);
        } finally {
            setWaiting(false);
        }
    }
    
    void NotesJMI_actionPerformed(java.awt.event.ActionEvent evt) {
        if (notes.notesPresent == false) {
            notes.JTA_Notes.setText(table.getData().getWepsManFileNotes());
            notes.setVisible(true);
            //Position this frame relative to the position of Mcrew-by Neha
            notes.setLocationRelativeTo(this);
            notes.notesPresent = true;
        } else if (notes.isActive() == false) {
            notes.JTA_Notes.setText(table.getData().getWepsManFileNotes());
            notes.toFront();
            notes.setVisible(true);
            notes.requestFocus();
        }
    }
    
    void InsertJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setWaiting(true);
        try {
            setUndoDeleteStatus(false);
            table.insertRow();
        } finally {
            setWaiting(false);
        }

    }

    public void SortJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setWaiting(true);
        try {
            setUndoDeleteStatus(false);
            table.sortData();
            table.checkData();
        } finally {
            setWaiting(false);
        }
    }
    
    void InsertFileJMI_actionPerformed(java.awt.event.ActionEvent event) {
        //if( table.isOneRowSelected("insert file") ) return;
        setWaiting(true);
        try {
            ManageData dataToInsert = new ManageData();

            TFile dirXML = new TFile(MCREWConfig.getDirectoryName(XMLConstants.smanagement_template));
            WepsFileChooser mfc;

            mfc = WepsFileChooser.create(WepsFileChooser.Action.Select, dirXML, false, false, null, WepsFileTypes.Management,
                    WepsFileTypes.Rotation);
            mfc.setCurrentDirectory(dirXML); //new de.schlichtherle.truezip.file.File(ConfigData.INITIAL_DIR));

            mfc.setDialogTitle("Select a Management File");

            //set the tooltip of "home" button to "Home" instead of "Desktop"
            mfc.homeToolTip(mfc);
            //remove the NewFolder button
            mfc.disableNewFolder(mfc);

            if (!(mfc.showDialog(null) == WepsFileChooser.APPROVE_OPTION)) {
                return;
            }
            TFile selectedFile = new TFile(mfc.getSelectedFile());

            try {
                String filePath = selectedFile.getCanonicalPath();
                //System.out.println("Mcrew:InsertFileJMI(): " + "Opening file " + filePath);
                dataToInsert.readDataFile(filePath);
                table.insertFile(dataToInsert, false, false);
                table.checkData();
                //savePath = delectedFile.getParent();
            } catch (IOException e) {
                System.err.println("Error in opening file " + e);
            }
            setDataChanged(true);
        } finally {
            setWaiting(false);
        }

    }
    
    void InsertFileDateAdjustedJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setWaiting(true);
        try {
            if (table.getData().getRows().isEmpty()) {
                InsertFileJMI_actionPerformed(event);
                return;
            }
            ManageData dataToInsert = new ManageData();

            TFile dirXML = new TFile(MCREWConfig.getDirectoryName(XMLConstants.smanagement_template));
            WepsFileChooser mfc;

            mfc = WepsFileChooser.create(WepsFileChooser.Action.Select, dirXML, false, false, null, WepsFileTypes.Management,
                    WepsFileTypes.Rotation);
            mfc.setCurrentDirectory(dirXML); //new de.schlichtherle.truezip.file.File(ConfigData.INITIAL_DIR));
            mfc.setDialogTitle("Select a Management File");

            //set the tooltip of "home" button to "Home" instead of "Desktop"
            mfc.homeToolTip(mfc);
            //remove the NewFolder button
            mfc.disableNewFolder(mfc);

            if (!(mfc.showDialog(null) == WepsFileChooser.APPROVE_OPTION)) {
                return;
            }
            TFile selectedFile = new TFile(mfc.getSelectedFile());

            try {
                String filePath = selectedFile.getCanonicalPath();
                //System.out.println("Mcrew:InsertFileJMI(): " + "Opening file " + filePath);
                dataToInsert.readDataFile(filePath);
                table.insertFile(dataToInsert, true, false);
                table.checkData();
                //savePath = delectedFile.getParent();
            } catch (IOException e) {
                System.err.println("Error in opening file " + e);
            }

            setDataChanged(true);
        } finally {
            setWaiting(false);
        }
    }
    
    void AddRotationDateAdjustedJMI_actionPerformed(java.awt.event.ActionEvent event) {
        setWaiting(true);
        try {

            ManageData dataToInsert = new ManageData();

            TFile dirXML = new TFile(MCREWConfig.getDirectoryName(XMLConstants.smanagement_template));
            WepsFileChooser mfc;

            mfc = WepsFileChooser.create(WepsFileChooser.Action.Select, dirXML, WepsFileTypes.Rotation);
            mfc.setCurrentDirectory(dirXML); //new de.schlichtherle.truezip.file.File(ConfigData.INITIAL_DIR));
            mfc.setDialogTitle("Select a Rotation File");

            //set the tooltip of "home" button to "Home" instead of "Desktop"
            mfc.homeToolTip(mfc);
            //remove the NewFolder button
            mfc.disableNewFolder(mfc);

            if (!(mfc.showDialog(null) == WepsFileChooser.APPROVE_OPTION)) {
                return;
            }
            TFile selectedFile = new TFile(mfc.getSelectedFile());

            try {
                String filePath = selectedFile.getCanonicalPath();
                //System.out.println("Mcrew:InsertFileJMI(): " + "Opening file " + filePath);
                dataToInsert.readDataFile(filePath);
                table.insertFile(dataToInsert, true, true);
                table.checkData();
                //savePath = delectedFile.getParent();
            } catch (IOException e) {
                System.err.println("Error in opening file " + e);
            }

            setDataChanged(true);
        } finally {
            setWaiting(false);
        }
    }
    
    // SymAction is overridden here to allow the popup menu objects to
    // be included in the list
    class SymAction implements java.awt.event.ActionListener {

        @Override
        public void actionPerformed(java.awt.event.ActionEvent event) {

            Object object = event.getSource();

            if (object == popCutJMI) {
                CutJMI_actionPerformed(event);
            } else if (object == popCopyJMI) {
                CopyJMI_actionPerformed(event);
            } else if (object == popPasteJMI) {
                PasteJMI_actionPerformed(event);
            } else if (object == popDeleteJMI) {
                DeleteJMI_actionPerformed(event);
            } else if (object == popUndoDeleteJMI) {
                UndoDeleteJMI_ActionPerformed(event);
            } else if (object == popInsertJMI) {
                InsertJMI_actionPerformed(event);
            } else if (object == popInsertOperationJMI) {
               InsertOperationJMI_actionPerformed(event);
            } else if (object == popInsertFileJMI) {
                // added by Sada
               InsertFileJMI_actionPerformed(event);
            } else if (object == popInsertFileDateAdjustedJMI) {
                // added by Sada
                InsertFileDateAdjustedJMI_actionPerformed(event);
            } else if (object == popAddRotationDateAdjustedJMI) {
                AddRotationDateAdjustedJMI_actionPerformed(event);
            } else if (object == popDrillDownScreenJMI) {
                // added by Sada
                DrillDownScreenJMI_actionPerformed(event);
            } else if (object == popSetDateJMI) {
                SetDateJMI_actionPerformed(event);
            } else if (object == popAdjustDateJMI) {
                ChangeDateJMI_actionPerformed(event);
            } else if (object == setDateJMI) {
                SetDateJMI_actionPerformed(event);
            } else if (object == calendarDateJMI) {
                CalendarDateJMI_actionPerformed(event);
            } else if (object == dateChangeDateJMI) {
                ChangeDateJMI_actionPerformed(event);
            } else if (object == dateIncrementYearJMI) {
                table.changeDates(Calendar.YEAR, 1);
                getCoordinator().dateChange(this);
            } else if (object == dateDecrementYearJMI) {
                table.changeDates(Calendar.YEAR, -1);
                getCoordinator().dateChange(this);
            } else if (object == dateIncrementMonthJMI) {
                table.changeDates(Calendar.MONTH, 1);
                getCoordinator().dateChange(this);
            } else if (object == dateDecrementMonthJMI) {
                table.changeDates(Calendar.MONTH, -1);
                getCoordinator().dateChange(this);
            } else if (object == dateIncrementWeekJMI) {
                table.changeDates(Calendar.DATE, 7);
                getCoordinator().dateChange(this);
            } else if (object == dateDecrementWeekJMI) {
                table.changeDates(Calendar.DATE, -7);
                getCoordinator().dateChange(this);
            } else if (object == dateIncrementDayJMI) {
                table.changeDates(Calendar.DATE, 1);
                getCoordinator().dateChange(this);
            } else if (object == dateDecrementDayJMI) {
                table.changeDates(Calendar.DATE, -1);
                getCoordinator().dateChange(this);
            } else if ((object == operationScreenJMI) || (object == cropScreenJMI)) {
                DrillDownScreenJMI_actionPerformed(event);
            } else if (object == addChangeOperationJMI){
                table.addColumnData(1);
            } else if(object == operationNotesJMI) {
                table.showNotes(1);
            } else if(object == addChangeCropJMI) {
                table.addColumnData(2);
            } else if(object == cropNotesJMI) {
                table.showNotes(2);
            } else if (object == setDirectionJMI) {
                SetDirectionJMI_actionPerformed(event);
            } else if (object == adjustDirectionJMI) {
                AdjustDirectionJMI_actionPerformed(event);
            } else if (object == setTozeroJMI) {
                SetToZeroJMI_actionPerformed(event);
            } else if (object == setTo45JMI) {
                SetTo45JMI_actionPerformed(event);
            } else if (object == setTo90JMI) {
                SetTo90JMI_actionPerformed(event);
            } else if (object == incrementBy15JMI) {
                IncrementBy15JMI_actionPerformed(event);
            } else if (object == decrementBy15JMI) {
                DecrementBy15JMI_actionPerformed(event);
            } else if (object == incrementBy45JMI) {
                IncrementBy45JMI_actionPerformed(event);
            } else if (object == decrementBy45JMI) {
                DecrementBy45JMI_actionPerformed(event);
            } else if (object == changeBy90JMI) {
                ChangeBy90JMI_actionPerformed(event);
                //Start here
            }
        }
    }
    
    
    /**
     * Saves the table to a .man file.
     */
    @SuppressWarnings("fallthrough")
    public void saveCurrent()
    {
        boolean resort = table.getData().IntView();
        switch(table.getData().getSave())
        {
            case NOSAVE:
                JOptionPane.showMessageDialog(null, "Unable to save:\nSome data out of limits.",
                "Management File", JOptionPane.INFORMATION_MESSAGE);
                return;
            case WARNSAVE:
                JOptionPane.showMessageDialog(null, "Warning:\nSome data out of recommended limits.",
                "Management File", JOptionPane.INFORMATION_MESSAGE);
                /*FallThrough*/
            default:
        }
        if ((fileName == null) || (fileName.length() == 0) || (fileName.equals(sUntitledFileName))) 
        {
            coordinator.saveCurrentAs();
            return;
        }

        //if file is xml and xml is not allowed, prompt to save as .man
        if (!usda.weru.util.ConfigData.getDefault().isFormatXMLAllowed() && fileName.toLowerCase().endsWith(".xml")) {
            coordinator.saveCurrentAs();
            return;

        }
        if(resort) coordinator.JMI_ItR_ActionPerformed(new ActionEvent(this, 2, ""));

        if (table.checkAllConditions() == false) {
            saveSuccess = false;
            if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
            return; // user pressed cancel on some option, Don't save
        }

        //If the use doesnt opens a file or opens a template of a file
        // and without making any changes saves the file, then the "absFileName"
        // should reflect this saved file.
        absFileName = filePathName;

        if (table.getDataChanged() == false) {
            if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
            return;
        }
        if ((savePath == null) || (savePath.length() == 0)) {
            savePath = MCREWConfig.getDirectoryName(XMLConstants.smanagement_template);

            ////System.out.println("Data changed " + dataChanged);
        }
        String fullPathFileName = savePath + TFile.separator + fileName;
        //System.out.println("MCREW : SaveJMI_aP : Saving file " + fullPathFileName);
        //Get the parent location of this file, see if its writable,if not
        //display the warning message and return.-by Neha
        TFile mcrewFile = new TFile(fullPathFileName);
        TFile parentFile = new TFile(mcrewFile.getParentFile());
        //System.out.println("SaveAsJMI_actionPerformed:parent file"+mcrewFile.getParent()+" can we write into this location:"+
        //parentFile.canWrite());
        if (parentFile.canWrite() == false) {
            JOptionPane.showMessageDialog(this, "The File location Specified is not writable\n " + fullPathFileName, "Error",
                    JOptionPane.ERROR_MESSAGE);
            if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
            return;
        }

        table.getData().writeDataFile(savePath + TFile.separator + fileName);
        //update the abs file path name to this path of the saved file
        absFileName = fullPathFileName;

        setDataChanged(false);
        saveSuccess = true;

        if (refreshMcrewScreen.equals("true")) {
            openRefreshedFile(absFileName);
            refreshMcrewScreen = "false";
        }
        if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
    }
    
    /**
     * Allows the user to choose a name and location, and saves the table with
     * said name and location.
     */
    @SuppressWarnings("fallthrough")
    public void saveCurrentAs()
    {
        boolean resort = table.getData().IntView();
        switch(table.getData().getSave())
        {
            case NOSAVE:
                JOptionPane.showMessageDialog(null, "Unable to save:\nSome data out of limits.",
                "Management File", JOptionPane.INFORMATION_MESSAGE);
                return;
            case WARNSAVE:
                JOptionPane.showMessageDialog(null, "Warning:\nSome data out of recommended limits.",
                "Management File", JOptionPane.INFORMATION_MESSAGE);
                /*FallThrough*/
            default:
        }
        RandomAccessFile in;
        long endPos;

        if(resort) coordinator.JMI_ItR_ActionPerformed(new ActionEvent(this, 2, ""));
        //System.out.println("");
        if (table.checkAllConditions() == false) {
            saveSuccess = false;
            if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
            return; // user pressed cancel on some option, Don't save
        }

        WepsFileChooser mfc;
        TFile tempFile;
        //  //System.out.println("savePath:"+savePath+"  coordinator.getProjectPath():"+coordinator.getProjectPath());
        if ((savePath == null) || (savePath.length() == 0)) {
            fileName = "untitled.man";
            //The file chooser dialog will open in the current WEPS directory.
            mfc = new WepsFileChooser(WepsFileChooser.Filetype.MANAGE, coordinator.getProjectPath(), WepsFileChooser.SAVE);
            mfc.setCurrentDirectory(new TFile(coordinator.getProjectPath())); //new de.schlichtherle.truezip.file.File(ConfigData.INITIAL_DIR));
            tempFile = new TFile(coordinator.getProjectPath(), fileName);
        } else if (!usda.weru.util.ConfigData.getDefault().isFormatXMLAllowed()) {
            //xml not allowed!
            mfc = new WepsFileChooser(WepsFileChooser.Filetype.MANAGE, savePath, WepsFileChooser.SAVE);
            String tempFileName = Util.purgeExtensions(fileName, WepsFileTypes.Management.getExtension());

            tempFile = new TFile(savePath, tempFileName);
            mfc.setCurrentDirectory(new TFile(savePath));
        } else {
            mfc = new WepsFileChooser(WepsFileChooser.Filetype.MANAGE, savePath, WepsFileChooser.SAVE);
            tempFile = new TFile(savePath, fileName);
            mfc.setCurrentDirectory(new TFile(savePath));
        }

        //set the tooltip of "home" button to "Home" instead of "Desktop"
        mfc.homeToolTip(mfc);
        mfc.setSelectedFile(tempFile);
        //                mfc.setText(tempFile.getName());
        mfc.setText(tempFile.getName());
        mfc.setDialogTitle("Save a Management File");

        if (mfc.showDialog(this) != WepsFileChooser.APPROVE_OPTION) {
            //            fileName = "";
            if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
            return;
        }
        TFile currentFile = new TFile(mfc.getSelectedFile());
        /* try{
         in = new RandomAccessFile(currentFile, "r");
         endPos = in.length(); // determine file length
         if( !( endPos > 0 ) ){
         JOptionPane.showMessageDialog(this, "CANNOT SAVE : Check for either empty rows or the file itself.",
         " Cannot Save file ",
         JOptionPane.INFORMATION_MESSAGE);
         if(resort)coordinator.JMI_WtN_ActionPerformed(new ActionEvent(this, 2, ""));
         return;
         }
         }catch(IOException e) {
         System.err.println(e.getMessage());
         }*/

        String newFileName = currentFile.getPath();
        //System.out.println("M_SA_aP: " + newFileName);
        TFile testFile = currentFile;
        TFile parentDir = new TFile(testFile.getParentFile());
        String name = testFile.getName();
        while (parentDir != null && !parentDir.exists()) {
            name = parentDir.getName() + TFile.separator + name;
            parentDir = new TFile(parentDir.getParentFile());
        }

        char[] invalidChars = {'\\', '/', '<', '>', '|', '?', '*', '&', '"', ':', '~', '`', '\''};
        //A single quote cannot be given as a character, so given as a separate string
        for (int i = 0; i < name.length(); i++) {
            for (int j = 0; j < invalidChars.length; j++) {
                if (name.charAt(i) == invalidChars[j]) {
                    JOptionPane.showMessageDialog(this, "INVALID CHARACTER : "
                            + invalidChars[j] + " \n\\ / < > | ? * & \" ~ ` ' ",
                            " Cannot Save file ", JOptionPane.INFORMATION_MESSAGE);
                    saveCurrentAs();
                    if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
                    return;
                }
            }
        }
        if (!mfc.getSelectedFile().getParentFile().exists()) {

            JOptionPane.showMessageDialog(this, "WRONG PATH : " + newFileName + " doesn't exist.", " Cannot Save file ",
                    JOptionPane.INFORMATION_MESSAGE);
            saveCurrentAs();
            if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
            return;
        }

        // strip suffix that filechooser seems to want to add
        if (newFileName.toUpperCase().endsWith(".MAN")) {
            newFileName = newFileName.substring(0, newFileName.lastIndexOf('.'));
            //System.out.println("MCREW : SaveAsJMI : New MAN_Filename is : " + newFileName );
        } else if (newFileName.toUpperCase().endsWith(".XML")) {
            newFileName = newFileName.substring(0, newFileName.lastIndexOf('.'));
        }

        String savedFile = null; //save the name of the file along with .man or .xml extension.

        // create .xml file if filter specified if
        int result = -1;
        if (mfc.accept(new TFile("x.xml"))) {
            result = table.getData().writeDataFile(newFileName + ".xml");
            savedFile = newFileName + ".xml";
        }

        //MUST DO THE MAN SECOND!! Make sure we use it in the run data.
        // create .man file if filter specified if
        if (mfc.accept(new TFile("x.man"))) {
            result = table.getData().writeDataFile(newFileName + ".man");
            savedFile = newFileName + ".man";
        }

        if (result != 1) {
            JOptionPane.showMessageDialog(this, "The File location Specified is not writable\n " + newFileName, "Error",
                    JOptionPane.ERROR_MESSAGE);
            if(resort)coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
            return;
        }

        fileName = new TFile(savedFile).getName();
        saveSuccess = true;

        try {
            table.getData().setWepsManFileNotes("");
            TFile fileDir = new TFile(savedFile);
            absFileName = fileDir.getCanonicalPath();
        } catch (IOException e) {
            System.err.println("Error in opening file " + e);
        }
        String message = null;
        //If Mcrew is not stand alone, append the message that mcrew will be closed
        changeRotFileName(savedFile);
        setDataChanged(false);
        if(resort)coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
    }
    
    /**
     * Saves the table as the file defined by the input String (path)
     * @param path 
     */
    @SuppressWarnings("fallthrough")
    public void saveCurrentWithName(String path)
    {
        boolean resort = table.getData().IntView();
        switch(table.getData().getSave())
        {
            case NOSAVE:
                JOptionPane.showMessageDialog(null, "Unable to save:\nSome data out of limits.",
                "Management File", JOptionPane.INFORMATION_MESSAGE);
                return;
            case WARNSAVE:
                JOptionPane.showMessageDialog(null, "Warning:\nSome data out of recommended limits.",
                "Management File", JOptionPane.INFORMATION_MESSAGE);
                /*FallThrough*/
            default:
        }

        if(resort) coordinator.JMI_ItR_ActionPerformed(new ActionEvent(this, 2, ""));
        if (table.checkAllConditions() == false) {
            saveSuccess = false;
            if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
            return;
        }

        TFile currentFile = new TFile(path);

        String newFileName = currentFile.getPath();
        TFile testFile = currentFile;
        TFile parentDir = new TFile(testFile.getParentFile());
        String name = testFile.getName();
        while (parentDir != null && !parentDir.exists()) {
            name = parentDir.getName() + TFile.separator + name;
            parentDir = new TFile(parentDir.getParentFile());
        }
        

        char[] invalidChars = {'\\', '/', '<', '>', '|', '?', '*', '&', '"', ':', '~', '`', '\''};
        //A single quote cannot be given as a character, so given as a separate string
        for (int i = 0; i < name.length(); i++) {
            for (int j = 0; j < invalidChars.length; j++) {
                if (name.charAt(i) == invalidChars[j]) {
                    JOptionPane.showMessageDialog(this, "INVALID CHARACTER : "
                            + invalidChars[j] + " \n\\ / < > | ? * & \" ~ ` ' ",
                            " Cannot Save file ", JOptionPane.INFORMATION_MESSAGE);
                    if(resort) coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
                    return;
                }
            }
        }
        
        int result = table.getData().writeDataFile(currentFile.getAbsolutePath());

        if (result != 1) {
            JOptionPane.showMessageDialog(this, "The File location Specified is not writable\n " + newFileName, "Error",
                    JOptionPane.ERROR_MESSAGE);
            if(resort)coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
            return;
        }

        fileName = currentFile.getName();
        saveSuccess = true;

        setDataChanged(false);
        if(resort)coordinator.JMI_RtI_ActionPerformed(new ActionEvent(this, 2, ""));
    }
    
    /**
     * Allows the user to choose a name and location, and saves the table with
     * said name and location.  The default location is set to the DB directory.
     */
    public void saveCurrentAsTemplate()
    {
        
        //System.out.println("Mcrew: SaveAsTJMI"+ "Save as Template file");
        if (table.checkAllConditions() == false) {
            return; // user pressed cancel on some option, Don't save
        }
        //if( (fileName == null) || (fileName.equals(sUntitledFileName)) )//(fileName.length() == 0) )

        String tempSaveAsPath = MCREWConfig.getDirectoryName(usda.weru.util.ConfigData.ManTempSaveAs);
        String tempPath = MCREWConfig.getDirectoryName(XMLConstants.smanagement_template);
        TFile dirXML = null;
        if (tempSaveAsPath != null && tempSaveAsPath.length() > 0 && MCREWConfig.getHasManTempSaveAsDir()) {
            dirXML = new TFile(tempSaveAsPath);
        } else {
            dirXML = new TFile(tempPath);
        }
        String dirXMLPath = dirXML.getAbsolutePath();

        TFile tempFile;
        tempFile = new TFile(dirXMLPath, fileName != null ? fileName : "Untitled");

        WepsFileChooser mfc = new WepsFileChooser(WepsFileChooser.Filetype.MANAGE, dirXMLPath, WepsFileChooser.SAVE);

        mfc.setCurrentDirectory(dirXML); //new de.schlichtherle.truezip.file.File(ConfigData.INITIAL_DIR));
        //set the tooltip of "home" button to "Home" instead of "Desktop"
        mfc.homeToolTip(mfc);
        mfc.setPersitSelectedFile(true);
        mfc.setSelectedFile(tempFile);
        mfc.setText(tempFile.getName());
        mfc.setDialogTitle("Save a Template Management File");
        if (mfc.showDialog(this) != WepsFileChooser.APPROVE_OPTION) {
            return;
        }
        TFile testFile = new TFile(mfc.getSelectedFile());
        TFile parentDir = new TFile(testFile.getParentFile());
        String name = testFile.getName();
        while (parentDir != null && !parentDir.exists()) {
            name = parentDir.getName() + TFile.separator + name;
            parentDir = new TFile(parentDir.getParentFile());
        }

        char[] invalidChars = {'\\', '/', '<', '>', '|', '?', '*', '&', '"', ':', '~', '`', '\''};
        //A single quote cannot be given as a character, so given as a separate string
        for (int i = 0; i < name.length(); i++) {
            for (int j = 0; j < invalidChars.length; j++) {
                if (name.charAt(i) == invalidChars[j]) {
                    JOptionPane.showMessageDialog(this, "INVALID CHARACTER : " + invalidChars[j] + " \n\\ / < > | ? * & \" ~ ` '",
                            " Cannot Save file ", JOptionPane.INFORMATION_MESSAGE);
                    saveCurrentAsTemplate();
                    return;
                }
            }
        }

        TFile selectedFile = new TFile(mfc.getSelectedFile());
        if (!selectedFile.getParentFile().exists()) {

            JOptionPane.showMessageDialog(this, "WRONG PATH : " + selectedFile.getPath()
                    + " doesn't exist.", " Cannot Save file ",
                    JOptionPane.INFORMATION_MESSAGE);
            saveCurrentAsTemplate();
            return;
        }

        String newFileName = selectedFile.getPath();

        // strip suffix that filechooser seems to want to add
        if (newFileName.toUpperCase().endsWith(".MAN")) {
            newFileName = newFileName.substring(0, newFileName.lastIndexOf('.'));
            //System.out.println("MCREW : SaveAsJMI : New MAN_Filename is : " + newFileName );
        } else if (newFileName.toUpperCase().endsWith(".XML")) {
            newFileName = newFileName.substring(0, newFileName.lastIndexOf('.'));
        }

        String savedFile = null; //save the name of the file along with .man or .xml extension.

        // create .xml file if filter specified if
        int result = -1;
        if (mfc.accept(new TFile("x.xml"))) {
            result = table.getData().writeDataFile(newFileName + ".xml");
            savedFile = newFileName + ".xml";
        }

        //MUST DO THE MAN SECOND!! Make sure we use it in the run data.
        // create .man file if filter specified if
        if (mfc.accept(new TFile("x.man"))) {
            result = table.getData().writeDataFile(newFileName + ".man");
            savedFile = newFileName + ".man";
        }

        if (result != 1) {
            JOptionPane.showMessageDialog(this, "The File location Specified is not writable\n " + newFileName, "Error",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }

        //setDataChanged(false);
        JOptionPane.showMessageDialog(this, savedFile, "Management file(s) template created", JOptionPane.INFORMATION_MESSAGE);

        //Comment out this line if you dont want to set the name of this file
        // to the rotation text field.
        //    RotationJT.setText(savedFilePath); // set the rotation file text area to last file saved
    }
    
    /**
     * Returns the path on which the file should save.
     * @return 
     */
    public String getSavePath() { return savePath; }
    public Table getTable() { return table; }
    
    public void doPrint() { table.doPrint(fileName); }
    
    @SuppressWarnings("fallthrough")
    public boolean checkSaveOnExit()
    {
        if (new TFile(absFileName).isDirectory()) {
            absFileName = "";
            fileName = "";
            filePathName = "";
        }
        if (table.getDataChanged()) 
        {
            int option = JOptionPane.showConfirmDialog(this, "Save current Management File ? ");
            switch (option) {
                case JOptionPane.CANCEL_OPTION:
                    return false;
                case JOptionPane.YES_OPTION:
                    switch(table.getData().getSave())
                    {
                        case NOSAVE:
                            JOptionPane.showMessageDialog(null, "Unable to save:\nSome data out of limits.",
                            "Management File", JOptionPane.INFORMATION_MESSAGE);
                            return false;
                        case WARNSAVE:
                            JOptionPane.showMessageDialog(null, "Warning:\nSome data out of recommended limits.",
                            "Management File", JOptionPane.INFORMATION_MESSAGE);
                            /*FallThrough*/
                        default:
                            if(!table.checkAllConditions()) return false;
                            if ((fileName == null) || (fileName.length() == 0) 
                                    || (fileName.equals(sUntitledFileName))) saveCurrentAs();
                            else saveCurrent(); 
                            break;
                    }
                case JOptionPane.NO_OPTION:
                    break;
            }
        }
        return true;
    }
    
    /**
     * Fires a property change.
     * @param name
     * @param oldValue
     * @param newValue 
     */
    public void firePropertyChange(String name, Object oldValue, Object newValue)
    {
        if(changes != null) changes.firePropertyChange(name, oldValue, newValue);
    }
    
    /**
     * Changes the icon to the right of rotation file name.
     * @param input 
     */
    void changeTableLabel(Icon input)
    {
        JL_iconHolder.setIcon(input);
        if(table.getData().IntView()) 
        {
            JTB_RtI.setIcon(Resources.getIcon("MCREWRotToggle.png"));
            JB_cycleBwd.setEnabled(false);
            JB_cycleFwd.setEnabled(false);
        }
        else 
        {
            JTB_RtI.setIcon(Resources.getIcon("MCREWIntToggle.png"));
            JB_cycleBwd.setEnabled(true);
            JB_cycleFwd.setEnabled(true);
        }
    }
    
    /**
     * This method will color the Rotation Years field with the ill wrapping color.
     */
    public void setIllWrap() { JTF_rotYears.setBackground(new Color(255,64,64)); }
    /**
     * This method will color the Rotation Years field with the default color (white).
     */
    public void clearIllWrap() { JTF_rotYears.setBackground(Color.WHITE); }
    
}
