/*
 * MCREWWindow.java
 *
 * Created on February 11, 2004, 11:35 AM
 */
package usda.weru.mcrew;

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TVFS;
import de.schlichtherle.truezip.file.swing.TFileChooser;
import de.schlichtherle.truezip.fs.FsSyncException;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import javax.help.CSH;
import javax.help.HelpBroker;
import javax.help.HelpSet;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JToggleButton;
import org.apache.log4j.Logger;
import org.openide.util.Exceptions;
import usda.weru.mcrew.SkelManConverter.XMLSkelFilter;
import usda.weru.mcrew.gui.MCREWWindow_n;
import usda.weru.mcrew.timeline.ComboTimeline;
import usda.weru.mcrew.timeline.TimelineConfig;
import usda.weru.mcrew.timeline.TimelineControls;
import usda.weru.mcrew.timeline.TimelinePanel;
import usda.weru.resources.Resources;
import usda.weru.util.About;
import usda.weru.util.AboutDialog;
import usda.weru.util.ConfigData;
import usda.weru.util.Help;
import usda.weru.util.Util;
import usda.weru.util.WepsFileChooser;
import usda.weru.util.WepsFileChooser.Filetype;
import usda.weru.util.WepsFileTypes;
import usda.weru.weps.Email;

/**
 * This class will be responsible for containing both the table objects and the
 * timeline objects, and interfacing between the two.
 * @author  jonathanhornbaker
 */
public class MCREWWindow extends MCREWWindow_n {
    
    public static void main(String[] args)
    {
        String mainConfig = "";
        String fileOrDir = "";
        for(int index = 0; index < args.length; index ++)
        {
            if(args[index].trim().equals("-cfg"))
            {
                index ++;
                mainConfig = args[index].trim();
            }
            if(args[index].trim().equals("-f")) 
            {
                index ++;
                fileOrDir = args[index];
            }
        }
        
        if(!mainConfig.equals(""))
        {
            mainConfig = Util.parse(mainConfig);
            TFile mainConfigFile = new TFile(mainConfig).getCanOrAbsFile();
            String userConfig = About.getUserWeps().getAbsolutePath() + "/" + mainConfigFile.getName();
            ConfigData.getDefault().load(mainConfigFile, new TFile(userConfig).getCanOrAbsFile());
        }
        String masterJar = "jar/MasterHelp.jar";
        Help.loadJar(masterJar);
        MCREWConfig.initialize(ConfigData.getDefault());
        System.setProperty("line.separator", "\n"); // make file line separator unix compatible
        // create an instance of mcrew
        
        String projDir = null;
        String[] fA = new String[0];
        if(!fileOrDir.equals(""))
        {
            TFile dest = new TFile(fileOrDir);
            if(dest.isDirectory()) projDir = dest.getAbsolutePath();
            else
            {
                fA = new String[1];
                fA[0] = dest.getAbsolutePath();
                projDir = dest.getParentFile().getAbsolutePath();
            }
        }
        
        if(projDir == null)
        {
            projDir = ConfigData.getDefault().getData(ConfigData.CurrentProj);
            if(projDir == null)
            {
                projDir = About.getUserDocuments().getAbsolutePath();
                int rtnVal = JOptionPane.showOptionDialog(null,
                        "MCREW needs a default directory location\n"
                        + "specified for it to store temporary files\n"
                        + "and to place save files.\n\n"
                        + "By default, this location is:\n"
                        + projDir,
                        "Warning (W-303)",
                        JOptionPane.DEFAULT_OPTION,
                        JOptionPane.WARNING_MESSAGE,
                        null,
                        new String[]{"Select", "Default"},
                        "Select");
                if(rtnVal == 0)
                {
                    WepsFileChooser wpc = new WepsFileChooser(WepsFileChooser.Filetype.DIR, ".",
                        WepsFileChooser.SELECT);
                    wpc.setCurrentDirectory(new TFile(projDir));
                    wpc.homeToolTip(wpc);
                    if (wpc.showDialog(null) == TFileChooser.APPROVE_OPTION) 
                    {
                        try 
                        {
                            TFile selProj = new TFile(wpc.getSelectedFile().getCanonicalPath());
                            projDir = selProj.getAbsolutePath();
                        } 
                        catch (IOException e) {}
                    }
                }
                
                ConfigData.getDefault().setData(ConfigData.CurrentProj, projDir);
                ConfigData.getDefault().save();
            }
        }
        MCREWWindow wind = new MCREWWindow("MCREW", projDir, fA, ConfigData.getDefault());
       
        wind.standaloneFlg = true;

        /* Disable Open copy of Template and Save as Template menu options when running standalone */
        wind.JMI_openCT.setEnabled(false);
        //mp.SaveAsTJMI.setEnabled(false);
        //When running stand-alone,the return arrow should not be displayed
        wind.JB_close.setVisible(false);
    }
    
    TablePanel tableObject;
    TimelinePanel timelineObject;
    ComboTimeline timelineStoragePanel;
    private static final Logger LOGGER = Logger.getLogger(TablePanel.class);
    public static final long serialVersionUID = 23789423789L;
    private boolean standaloneFlg = false;
    private List<String> c_guiViews;
    /**
     * 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;
    static {
        openMcrewWindows = new ArrayList<MCREWWindow>();
    }
    static List<MCREWWindow> openMcrewWindows;
    /**
     * Absolute Project directory path
     */
    private String projectDir = null;
    private ConfigData cd;
    private int dataChanged;
    
    /**
     * 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;
    /**
     * 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;
    //the table view of the data ...this is where everything happens
    private String columnConfig = "My Config Frame";
    /**
     * This shows the column config frame
     */
    private ConfigFrame configFrame = new ConfigFrame(columnConfig);//NEEDS HANDLING
    // Used by addNotify
    boolean frameSizeAdjusted = false;
    /**
     * Prefixe indicating parent application.
     */
    public static final String MCR = "MCREW-";
    /**
     * Prefixing to indicate parent object's window is open
     */
    public static final String WindowOpen = MCR + "WindowOpen";
    /**
     * Prefixing to indicate to which parent does the file belong.
     */
    public static final String FileName = MCR + "FileName";
    /**
     * Prefixing to indicate parent object's window close event.
     */
    public static final String WindowClosing = MCR + "WindowClosing";
    
    private SkelManConverter sMC;
    
    /**
     * Most basic constructor.  Not guaranteed to be Accurate.
     * @param files 
     */
    public MCREWWindow(String[] files)
    {
        this("MCREW Timeline Version 1.0", ConfigData.getDefault().getData(ConfigData.ProjDir), files, ConfigData.getDefault());
    }
    
    /**
     * Common constructor for MCREW.  Gives a title, sets project directory, etc.
     * @param title
     * @param projectDirectory
     * @param files
     * @param conDat 
     */
    public MCREWWindow(String title, String projectDirectory, String[] files, ConfigData conDat)
    {
        super();
        projectDir = projectDirectory;
        this.setTitle(title);
        System.setProperty("line.separator", "\n");
        MCREWConfig.initialize(conDat);
        JTB_autoSort.setSelected(MCREWConfig.autosort);
//        TimelineConfig.initialize();
        
        TimelinePanel time = new TimelinePanel(files, this);
        TimelineControls controls = new TimelineControls(time);
        time.linkControls(controls);
        timelineStoragePanel = new ComboTimeline(time, controls);
        timelineObject = time;
        if(files == null || files.length == 0 || (files.length == 1 && files[0].trim().equals(""))) this.addNew();
        TablePanel mp = time.getTablePanel(0);
        
        timelineContainer.add(timelineStoragePanel);
        javax.swing.GroupLayout timePanelLayout = new javax.swing.GroupLayout(timelineContainer);
        timelineContainer.setLayout(timePanelLayout);
        timePanelLayout.setHorizontalGroup(
            timePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(timelineStoragePanel).addGap(10, 10, Short.MAX_VALUE)
        );
        timePanelLayout.setVerticalGroup(
            timePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(timelineStoragePanel).addGap(10, 10, Short.MAX_VALUE)
        );
        
        tableContainer.add(mp);
        javax.swing.GroupLayout tabelPanelLayout = new javax.swing.GroupLayout(tableContainer);
        tableContainer.setLayout(tabelPanelLayout);
        tabelPanelLayout.setHorizontalGroup(
            tabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mp).addGap(10, 10, Short.MAX_VALUE)
        );
        tabelPanelLayout.setVerticalGroup(
            tabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mp).addGap(10, 10, Short.MAX_VALUE)
        );
        
        c_guiViews = new ArrayList<String>();
        
        mp.setLocation(10, 10);
        
        mp.addToMain(mp.table);
        
        mp.setVisible(true);
        timelineStoragePanel.setVisible(true);
        this.setVisible(true);
        tableObject = mp;
        tableObject.table.focusTable();
        if(files.length == 0) tableObject.savePath = projectDirectory;
        
        setupViews();
        DefaultViewJMI_actionPerformed(new ActionEvent(this, 0, ""));
        
        if(ConfigData.isSingleFileMode()) singleFileMode();
        if(conDat.getData(ConfigData.McrewEdit).trim().equals("0")) disableOpens();
        cd = conDat;
        
        
        Util.loadToolTips((Container) this, new TFile("mcrew_cfg", "mcrewtooltips.cfg"));
        this.addHelp();
        openMcrewWindows.add(this);
    }
    
    /**
     * Brings the currently selected table panel to the forefront (i.e. makes it visible)
     */
    public void refocus() { refocus(timelineObject.getSelectedIndex()); }

    /**
     * Brings the table at the specified index in the timeline to the forefront.
     * @param index 
     */
    public void refocus(int index)
    {
        tableContainer.remove(tableObject);
        TablePanel mp = timelineObject.getTablePanel(index);
        tableContainer.add(mp);
        javax.swing.GroupLayout tabelPanelLayout = new javax.swing.GroupLayout(tableContainer);
        tableContainer.setLayout(tabelPanelLayout);
        tabelPanelLayout.setHorizontalGroup(
            tabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mp).addGap(10, 10, Short.MAX_VALUE)
        );
        tabelPanelLayout.setVerticalGroup(
            tabelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mp).addGap(10, 10, Short.MAX_VALUE)
        );
        mp.setLocation(10, 10);
        mp.addToMain(mp.table);
        mp.setVisible(true);
        tableObject = mp;
        tableObject.table.focusTable();
    }
    
    /**
     *
     * @return
     */
    public static boolean isOpen() {
        return MCREWWindow.openMcrewWindows.size() > 0;
    }
    
    public String getProjectPath() { return projectDir; }
    public ConfigData getCD() { return cd; }
    
    /**
     * This is some legacy functionality.  When the enabled full MCREW editing functionality
     * is off, we need to disable opens that touch the project directory.  Don't know why.
     */
    public void disableOpens()
    {
        JMI_open.setEnabled(false);
        JMI_addOpen.setEnabled(false);
        JMI_overOpen.setEnabled(false);
        tableObject.JB_open.setEnabled(false);
    }
      
    /**
     * Transforms a table in WEPS Rotation View into Crop Interval View.
     * @param evt 
     */
    protected void JMI_RtI_ActionPerformed(java.awt.event.ActionEvent evt)
    {
        tableObject.table.getData().rotToIntSort();
        JMI_RotSort.setEnabled(tableObject.table.getData().IntView());
        JMI_IntSort.setEnabled(!tableObject.table.getData().IntView());
        JMI_cycleBwd.setEnabled(false);
        JMI_cycleFwd.setEnabled(false);
        tableObject.changeTableLabel(TablePanel.intMode);
    }
    
    /**
     * Transforms a table in Crop Interval View to WEPS Rotation View.
     * @param evt 
     */
    protected void JMI_ItR_ActionPerformed(java.awt.event.ActionEvent evt)
    {
        try { tableObject.table.getData().inttoRotSort(); }
        catch(Exception ex)
        {
            String val = ex.getMessage();
            int newRotYears;
            try { newRotYears = Integer.parseInt(val); }
            catch(NumberFormatException nfe) { newRotYears = tableObject.table.getData().kRotationYears + 1; }
            if(JOptionPane.showConfirmDialog(null, "Number of years in rotation greater than"
                    + "\nNumber of years specified.  Do you wish to set the number of rotation\n"
                    + "years to " + newRotYears + "?",
                    "Invalid Date", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
            {
                tableObject.table.getData().setRotationYears(newRotYears);
                JMI_ItR_ActionPerformed(evt);
                return;
            }
            else return;
        }
        JMI_RotSort.setEnabled(tableObject.table.getData().IntView());
        JMI_IntSort.setEnabled(!tableObject.table.getData().IntView());
        JMI_cycleBwd.setEnabled(true);
        JMI_cycleFwd.setEnabled(true);
        tableObject.changeTableLabel(TablePanel.rotMode);
    }

    /**
     * This method notifies when the window or frame is resized and the components need to be
     * re-arranged so they are evenly spaced relative to each other.
     */
    @Override
    public void addNotify() {
        //Dimension size = getSize();
        super.addNotify();

        if (frameSizeAdjusted) {
            return;
        }
        frameSizeAdjusted = true;

    }

    /**
     * Prints the table.
     *
     * @param event
     */
    @Override
    public void PrintJMI_actionPerformed(java.awt.event.ActionEvent event) {
       tableObject.doPrint();
    }

    /**
     * This method is called when the exit option is selected
     *
     * @param event
     */
    @Override
    @SuppressWarnings("fallthrough")
    public void ExitJMI_actionPerformed(java.awt.event.ActionEvent event) {
        tableObject.commitEdit();

        int option = -1;
        boolean closeWindow = false;
        
        Object[] options = {"Yes", "No", "View Each", "Cancel"};
        if(dataChanged > 0)
        {
            int selection = JOptionPane.showOptionDialog(this, "Save All Modified "
                + "Management Files?", "Save All?", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, 
                null, options, options[3]);
            switch(selection)
            {
                case 0:
                    saveAll();
                case 1: /*FALLTHROUGH*/
                    closeWindow = true;
                    break;
                case 2:
                    closeWindow = checkandSaveAll();
                    break;
                default:
            }
        }
        else closeWindow = true;

        if (closeWindow) {
            tableObject.firePropertyChange(WindowClosing, null, "true");
            clearAndDispose();
            openMcrewWindows.remove(this);
            for(int index = 0; index < timelineObject.getNumFiles(); index ++)
            {
                TablePanel tempTable = timelineObject.getTablePanelNoSelect(index);
                tempTable.table.setKillFlag(true);
            }
            this.setVisible(false);
            this.dispose();
            if (standaloneFlg) {
                System.exit(0);
            }
        } //end of if
    }

    /**
     * Opens the MCREW Configuration window.
     * @param event 
     */
    @Override
    public void ConfigurationJMI_actionPerformed(java.awt.event.ActionEvent event) {
        // Display Configuration screen
        configFrame.setVisible(true);
    }

    /**
     * Opens the MCREW Configuration window.
     * @param event 
     */
    @Override
    public void ColumnOptionsJMI_actionPerformed(java.awt.event.ActionEvent event) {
        // //System.out.println("Setting up Column Configuration panel " );
        configFrame.setVisible(true);
    }

    /**
     * Fires an email event to the desktop, which will redirect to the default mail
     * client of the host.
     * @param event 
     */
    @Override
    public void EmailJMI_actionPerformed(java.awt.event.ActionEvent event) {
        try {
            /**
             * projectsPath is the directory in which the projects are present projectDirectory is
             * the directory in which the current run is present. These both are needed for the File
             * Choosers in the Email
             *
             */
            //Email em = new Email("Send Email to WEPS Support", "", "weps-comments@weru.ksu.edu","MCrew", absFileName);
            Email.comment("MCREW", null, tableObject.absFileName);
        } catch (java.lang.Exception e) {
        }
    }

    @Override
    public void HelpJMI_actionPerformed(java.awt.event.ActionEvent event) {
        // implement it
    }

    /**
     * Loads the about dialogue.  
     * @param event 
     */
    @Override
    public void AboutJMI_actionPerformed(java.awt.event.ActionEvent event) {
        try {
            // JAboutDialog Create with owner and show as modal
            AboutDialog JAboutDialog1 = new AboutDialog(this, usda.weru.util.Application.MCREW);
            JAboutDialog1.setModal(true);
            JAboutDialog1.setVisible(true);
        } catch (Exception e) {
        }
    }

    /**
     * This function updates WEPS Management individual files -added by Neha
     * @param evt 
     */
    @Override
    public void UpdateFilesJMI_actionPerformed(java.awt.event.ActionEvent evt) {
        try {
            // Step 1: Prompt for the .man files that need to be updated
            String m_fileName = "";

            WepsFileChooser fileChooser = WepsFileChooser.create(WepsFileChooser.Action.Select, null, false, true, null,
                    WepsFileTypes.Management, WepsFileTypes.Rotation);
            fileChooser.setFileSelectionMode(WepsFileChooser.FILES_ONLY);
            fileChooser.setMultiSelectionEnabled(true);
            fileChooser.setAcceptAllFileFilterUsed(false);
            fileChooser.setApproveButtonText("Select Files");

            fileChooser.setDialogTitle("Select WEPS management files that are to be updated");

            String dir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_template);
            TFile ddir = new TFile(dir);
            fileChooser.setCurrentDirectory(ddir);

            java.io.File[] sourceFiles = null;
            int returnVal = fileChooser.showOpenDialog(this);
            if (returnVal == WepsFileChooser.APPROVE_OPTION) {
                sourceFiles = fileChooser.getSelectedFiles();
            } else {
                return;
            }
            //Check if all the files selected are management files and put them in a vector
            boolean doUpdate = true;
            List<String> manFiles = new ArrayList<String>();
            for (int i = 0; sourceFiles != null && i < sourceFiles.length; i++) {
                try {
                    m_fileName = sourceFiles[i].getCanonicalPath();
                    doUpdate = WepsFileTypes.Management.accept(sourceFiles[i]) || WepsFileTypes.Rotation.accept(sourceFiles[i]);
                    if (doUpdate == false) {
                        JOptionPane.showMessageDialog(this, m_fileName
                                + "\n\nSelection is not a WEPS management or rotation file.\n\nNo Files Updated.",
                                "WEPS Information", JOptionPane.ERROR_MESSAGE);
                    }
                    manFiles.add(m_fileName);
                } catch (HeadlessException | IOException e) {
                    System.out.println("Error: " + e);
                }
            }

            if (doUpdate == false) {
                return;
            }

            TFile fs = new TFile(MCREWConfig.getDirectoryName(XMLConstants.smanagement_skeleton));
            if ((!fs.exists()) || (!fs.isDirectory())) {
                JOptionPane.showMessageDialog(this, "Skeleton directory is not valid: \n\n"
                        + MCREWConfig.getDirectoryName(XMLConstants.smanagement_skeleton),
                        "Error", JOptionPane.INFORMATION_MESSAGE);
                return;
            }

            //Give the doUpdate() function the vector containing the names of the man files to be updated.
            XMLManagementUpdater updateMan = new XMLManagementUpdater();
            updateMan.doUpdate(this, manFiles);
            TVFS.umount();
        } catch (FsSyncException ex) {
            java.util.logging.Logger.getLogger(TablePanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    } //end of updateFilesJMI_actionPerformed
    
    /**
     * Prints out the selected file in the 1.5 management file format.
     * @param evt 
     */
    @Override
    public void BackConvertSingleJMI_actionPerformed(ActionEvent evt)
    {
        TFile sourceFile = null;
        TFile destinationDirectory = null;
        {
            WepsFileChooser fileChooser = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
            fileChooser.setFileSelectionMode(WepsFileChooser.FILES_ONLY);
            fileChooser.setMultiSelectionEnabled(false);
            fileChooser.setApproveButtonText("Choose File");
            XMLSkelFilter filter = new XMLSkelFilter("man", "WEPS Management Files");
            fileChooser.setFileFilter(filter);
            fileChooser.setDialogTitle("Select a WEPS management file");

            TFile ddir = new TFile(tableObject.savePath);
            fileChooser.setCurrentDirectory(ddir);

            int returnVal = fileChooser.showOpenDialog(this);

            if (returnVal == WepsFileChooser.APPROVE_OPTION) 
            {
                try { sourceFile = new TFile(fileChooser.getSelectedFile()); } 
                catch (Exception e) { System.err.println("Error: " + e); }
            } 
            else return;
        }
        {
            WepsFileChooser fileChooser = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
            fileChooser.setFileSelectionMode(WepsFileChooser.DIRECTORIES_ONLY);
            fileChooser.setMultiSelectionEnabled(false);
            fileChooser.setDialogTitle("Select a destination directory.");
            fileChooser.setAcceptAllFileFilterUsed(false);
            fileChooser.setApproveButtonText("Choose Directory");
            
            TFile ddir = new TFile(tableObject.savePath);
            fileChooser.setCurrentDirectory(ddir);

            int returnVal = fileChooser.showOpenDialog(this);

            if (returnVal == WepsFileChooser.APPROVE_OPTION) 
            {
                try { destinationDirectory = new TFile(fileChooser.getSelectedFile().getCanonicalPath() + TFile.separator); } 
                catch (Exception e) { System.err.println("Error: " + e); }
            } 
            else return;
        }
        if((sourceFile == null) || (destinationDirectory == null)) return;
        String destPath = destinationDirectory.getAbsolutePath() + TFile.separator + sourceFile.getName();
        if(sourceFile.getParent().equals(destinationDirectory.getAbsolutePath()))
        {
            destPath = destPath.trim().substring(0, destPath.lastIndexOf("."))
                    + "Ver15.man";
        }
        TFile destFile = new TFile(destPath);
        ManageData temp = new ManageData();
        temp.readDataFile(sourceFile.getAbsolutePath());
        temp.writeOldFile(destFile.getAbsolutePath());
    }
            
    /**
     * Prints out a directory of management files in the 1.5 management file format.
     * @param evt 
     */
    @Override
    public void BackConvertRecursiveJMI_actionPerformed(ActionEvent evt)
    {
        TFile sourceDirectory = null;
        TFile destinationDirectory = null;
        {
            WepsFileChooser fileChooser = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
            fileChooser.setFileSelectionMode(WepsFileChooser.DIRECTORIES_ONLY);
            fileChooser.setMultiSelectionEnabled(false);
            fileChooser.setDialogTitle("Select a source directory.");
            fileChooser.setAcceptAllFileFilterUsed(false);
            fileChooser.setApproveButtonText("Choose Directory");
            
            TFile ddir = new TFile(tableObject.savePath);
            fileChooser.setCurrentDirectory(ddir);

            int returnVal = fileChooser.showOpenDialog(this);

            if (returnVal == WepsFileChooser.APPROVE_OPTION) 
            {
                try { sourceDirectory = new TFile(fileChooser.getSelectedFile().getCanonicalPath() + TFile.separator); } 
                catch (Exception e) { System.err.println("Error: " + e); }
            } 
            else return;
        }
        {
            WepsFileChooser fileChooser = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
            fileChooser.setFileSelectionMode(WepsFileChooser.DIRECTORIES_ONLY);
            fileChooser.setMultiSelectionEnabled(false);
            fileChooser.setDialogTitle("Select a destination directory.");
            fileChooser.setAcceptAllFileFilterUsed(false);
            fileChooser.setApproveButtonText("Choose Directory");
            
            TFile ddir = new TFile(tableObject.savePath);
            fileChooser.setCurrentDirectory(ddir);

            int returnVal = fileChooser.showOpenDialog(this);

            if (returnVal == WepsFileChooser.APPROVE_OPTION) 
            {
                try { destinationDirectory = new TFile(fileChooser.getSelectedFile().getCanonicalPath() + TFile.separator); } 
                catch (Exception e) { System.err.println("Error: " + e); }
            } 
            else return;
        }
        if((sourceDirectory == null) || (destinationDirectory == null)) return;
        String extension = ".man";
        if(sourceDirectory.getAbsolutePath().equals(destinationDirectory.getAbsolutePath()))
        {
            extension = "Ver15.man";
        }
        convertDirectoryToArchive(sourceDirectory, destinationDirectory, extension);
    }
    
    /**
     * This method handles the meat and potatoes of converting a directory of management
     * files into the 1.5 management file format.
     * @param sourceDirectory
     * @param destinationDirectory
     * @param newExtension 
     */
    public void convertDirectoryToArchive(TFile sourceDirectory, TFile destinationDirectory, String newExtension)
    {
        for(TFile sourceFile : sourceDirectory.listFiles())
        {
            if(sourceFile.isDirectory())
            {
                String newDestPath = destinationDirectory.getAbsolutePath() + 
                        TFile.separator + sourceFile.getName() + TFile.separator;
                TFile newDest = new TFile(newDestPath);
                convertDirectoryToArchive(sourceFile, newDest, newExtension);
            }
            else if(sourceFile.getAbsolutePath().trim().endsWith(".man"))
            {
                String destPath = destinationDirectory.getAbsolutePath() + 
                        TFile.separator + sourceFile.getName();
                destPath = destPath.trim().substring(0, destPath.lastIndexOf("."))
                    + newExtension;
                TFile destFile = new TFile(destPath);
                ManageData temp = new ManageData();
                temp.readDataFile(sourceFile.getAbsolutePath());
                temp.writeOldFile(destFile.getAbsolutePath());
            }
        }
    }

    /**
     * This function updates the WEPS Management files recursively.
     * @param event 
     */
    @Override
    public void UpdateWEPSJMI_actionPerformed(java.awt.event.ActionEvent event) {
        //  implement it;
        String dir;
        WepsFileChooser fileChooserMan = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
        fileChooserMan.setFileSelectionMode(WepsFileChooser.DIRECTORIES_ONLY);
        fileChooserMan.setMultiSelectionEnabled(false);
        fileChooserMan.setDialogTitle("Select a directory where all WEPS management files will be updated");
        fileChooserMan.setAcceptAllFileFilterUsed(false);

        dir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_template);
        TFile ddir = new TFile(dir);

        fileChooserMan.setApproveButtonText("Choose Directory");
        fileChooserMan.setCurrentDirectory(ddir);

        int returnVal = fileChooserMan.showOpenDialog(this);
        if (returnVal == WepsFileChooser.APPROVE_OPTION) {
            try {
                try {
                    dir = fileChooserMan.getSelectedFile().getCanonicalPath() + TFile.separator;
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                }
                TFile testdir = new TFile(dir);
                if ((!testdir.exists()) || testdir.isFile()) {
                    JOptionPane.showMessageDialog(this, dir + "\n\nSelection is not a directory.", "WEPS Information",
                            JOptionPane.ERROR_MESSAGE);
                    return;
                }
            } catch (HeadlessException e) {
                System.out.println("Error: " + e);
            }
        } else {
            return;
        }
        if (JOptionPane.showConfirmDialog(this, "This will update all the WEPS management files in the management directory:\n"
                + dir + "\nwith current information from the operation and crop files.\n\nThis will also update all "
                + "WEPS management files in all subdirectores under \n" + dir
                + "\n\nDo you want to update the WEPS management files now?", "Update WEPS Management Files",
                JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
            return;
        }
        //set the cursor to wait cursor on the Mcrew screen
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

        XMLManagementUpdater updater = new XMLManagementUpdater();
        updater.updateDirectory(this, dir, true);
        //set the cursor back to default on the Mcrew screen
        setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }

    @Override
    protected void HelpJB_actionPerformed(java.awt.event.ActionEvent event) {
        HelpJMI_actionPerformed(event);
    }

    /**
     * Closes the MCREW Window.
     * @param evt 
     */
    @Override
    public void JBClose_actionPerformed(java.awt.event.ActionEvent evt) {

        ExitJMI_actionPerformed(evt);
    }
    
    /**
     * Takes the currently selected rows and adds them to the clipboard.
     * @param evt 
     */
    @Override 
    protected void CopyJMI_actionPerformed(ActionEvent evt) { tableObject.CopyJMI_actionPerformed(evt); } 
    /**
     * Makes the last year in the table year one, and increments all other years.
     * @param evt 
     */
    @Override 
    protected void CycleFwdJMI_actionPerformed(ActionEvent evt) { tableObject.CycleFwdJMI_actionPerformed(evt); } 
    /**
     * Makes the first year in the table the number of years in the rotation and
     * decrements all other years.
     * @param evt 
     */
    @Override 
    protected void CycleBwdJMI_actionPerformed(ActionEvent evt) { tableObject.CycleBwdJMI_actionPerformed(evt); } 
    /**
     * Adds a blank row into the table above the highest currently selected row.
     * @param evt 
     */
    @Override 
    protected void InsertJMI_actionPerformed(ActionEvent evt) { tableObject.InsertJMI_actionPerformed(evt); } 
    /**
     * Presents the user with a file chooser, so that they can select a .oprn file
     * to insert.  It then loads the data in that file into the row above.
     * @param evt 
     */
    @Override
    protected void InsertOperationJMI_actionPerformed(java.awt.event.ActionEvent evt) { tableObject.InsertOperationJMI_actionPerformed(evt); }
    /**
     * Iterates through each row in the table and places them in ascending order
     * by date.
     * @param evt 
     */
    @Override 
    protected void SortJMI_actionPerformed(ActionEvent evt) { tableObject.SortJMI_actionPerformed(evt); } 
    /**
     * This operation will remove the selected rows from the table.
     * @param evt 
     */
    @Override 
    protected void DeleteJMI_actionPerformed(ActionEvent evt) { tableObject.DeleteJMI_actionPerformed(evt); } 
    /**
     * Iff the operation immediately previous was delete, this will undo the 
     * changes made by that operation.
     * @param evt 
     */
    @Override
    public void UndoDeleteJMI_ActionPerformed(java.awt.event.ActionEvent evt) { tableObject.UndoDeleteJMI_ActionPerformed(evt); }
    /**
     * Inserts the rows on the clipboard above the highest currently selected row.
     * @param evt 
     */
    @Override 
    protected void PasteJMI_actionPerformed(ActionEvent evt) { tableObject.PasteJMI_actionPerformed(evt); } 
    /**
     * Takes the currently selected rows and adds them to the clipboard, then
     * deletes those rows.
     * @param evt 
     */
    @Override 
    protected void CutJMI_actionPerformed(ActionEvent evt) { tableObject.CutJMI_actionPerformed(evt); } 
    @Override 
    protected void NotesJMI_actionPerformed(ActionEvent evt) { tableObject.NotesJMI_actionPerformed(evt); }
   
    /**
     *
     * @param evt
     */
    @Override
    protected void DefaultViewJMI_actionPerformed(java.awt.event.ActionEvent evt) {
        for (String name : c_guiViews) {
            JCheckBoxMenuItem cmi = tableObject.getCmis(name);
            JToggleButton tb = tableObject.getTbs(name);

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

            if (tb != null) {
                tb.setSelected(false);
            }

            tableObject.handleViewToggle(name, false);
        }
        tableObject.handleViewToggle("default", true);
    }
    
    /**
     * A coordinator method for making sure all open template buttons are disabled
     * when they should be.
     */
    public void disableOpenButtons()
    {
        JMI_openCT.setEnabled(false);
    }
    /**
     * Coordinator method for ensuring all undo buttons and items are disabled
     * when undo delete is not an option.
     * @param enabled 
     */
    public void setUndoDeleteStatus(boolean enabled)
    {
        JMI_undoDelete.setEnabled(enabled);
    }
  
    /**
     * Appends an empty management to the table.  Sets the current table view
     * to that managment.
     */
    @Override
    public void addNew()
    {
        timelineObject.appendNewFile();
        
        //Set the current view to the new data.

        invalidate();
        repaint();
    }
    /**
     * Overwrite the currently selected Managedata with a new (empty) dataset.
     */
    @Override
    public void newOverwrite()
    {
        if(!tableObject.checkSaveOnExit()) return;
        tableObject.newFile();
        timelineObject.resynchSelected();

        invalidate();
        repaint();
    }
    /**
     * Adds an existing management file to the current dataset, makes that
     * the currently selected dataset.
     */
    @Override
    public void addExisting()
    {
        
        String path = findFile(tableObject.getSavePath());
        if(path == null) return;
        else timelineObject.appendExistingFile(path);
        //Sycnh table.

        invalidate();
        repaint();
    }
    /**
     * Overwrite the currently selected ManageData with the manageData chosen by
     * the user in the file chooser.
     */
    public void existingOverwrite()
    {
        if(!tableObject.checkSaveOnExit()) return;
        String path = findFile(tableObject.getSavePath());
        if(path == null) return;
        else tableObject.openFile(path);
        timelineObject.resynchSelected();

        invalidate();
        repaint();
    }
    /**
     * Add an existing template file to the current dataset, sets the table view to that.
     */
    @Override
    public void addTemplate()
    {
        TFile dirXML = new TFile(MCREWConfig.getDirectoryName(XMLConstants.smanagement_template));
        String dirXMLPath = dirXML.getAbsolutePath();
        String path = findFile(dirXMLPath);
        if(path == null) return;
        else
        {
            TFile selectedFile = new TFile(path);
            try 
            {
                String fileDir = selectedFile.getCanonicalPath();
                String m_fileName = selectedFile.getName();
                String copyToFilePath;

                copyToFilePath = projectDir + TFile.separator + m_fileName;
                if (usda.weru.util.Util.copyFile(fileDir, copyToFilePath) == false) {
                    JOptionPane.showMessageDialog(this, "Something wrong in copying the template file."
                            + "Try opening the file through Open File option", "Open copy of template", JOptionPane.OK_OPTION);
                    return;
                }
                timelineObject.appendExistingFile(copyToFilePath);
                TFile file = new TFile(fileDir);
                tableObject.saveTemplatePath = file.getParent();
            } catch (IOException e) {
                System.err.println("Error in opening file " + e);
            }
        }
    }
    /**
     * Overwrite the currently selected ManageData with the managedata generated by loading
     * the user specified template file.
     */
    @Override
    public void templateOverwrite()
    {
        if(!tableObject.checkSaveOnExit()) return;
        TFile dirXML = new TFile(MCREWConfig.getDirectoryName(XMLConstants.smanagement_template));
        String dirXMLPath = dirXML.getAbsolutePath();
        String path = findFile(dirXMLPath);
        if(path == null) return;
        else
        {
            TFile selectedFile = new TFile(path);
            try 
            {
                String fileDir = selectedFile.getCanonicalPath();
                String m_fileName = selectedFile.getName();
                String copyToFilePath;

                copyToFilePath = projectDir + TFile.separator + m_fileName;
                if (usda.weru.util.Util.copyFile(fileDir, copyToFilePath) == false) {
                    JOptionPane.showMessageDialog(this, "Something wrong in copying the template file."
                            + "Try opening the file through Open File option", "Open copy of template", JOptionPane.OK_OPTION);
                    return;
                }
                tableObject.openFile(copyToFilePath);
                timelineObject.resynchSelected();
                TFile file = new TFile(fileDir);
                tableObject.saveTemplatePath = file.getParent();
            } catch (IOException e) {
                System.err.println("Error in opening file " + e);
            }
        }
    }
    /**
     * Saves the current table into memory;  Uses table object to achieve result.
     */
    @Override
    public void saveCurrent() { tableObject.saveCurrent(); }
    /**
     * Saves the current table into memory with a different name.
     */
    @Override
    public void saveCurrentAs() 
    {
        tableObject.saveCurrentAs();
        //Do we have to fire a change at the timeline?
    }
    /**
     * Saves the current table into memor as a template.
     */
    @Override
    public void saveCurrentAsTemplate() 
    {
        tableObject.saveCurrentAsTemplate();
        //Do we have to fire a change at the timeline?
    }
    /**
     * Saves all currently open management files.
     */
    @Override
    public void saveAll()
    {
        timelineObject.saveAllFiles();
    }
    /**
     * Save all currently open management files, appending the user specified string
     * onto the end of the name and moving the files to the specified location.
     */
    @Override
    public void saveAllAs()
    {
        if(EventQueue.isDispatchThread())
        {
            Thread th = new Thread()
            {
                @Override
                public void run()
                {
                    ExtensionSelector ext = new ExtensionSelector(tableObject.savePath);
                    if(!ext.recieveInput())  return; 
                    for(int index = 0; index < timelineObject.getNumFiles(); index ++)
                    {
                        TablePanel tabPan = timelineObject.getTablePanelNoSelect(index);
                        tabPan.saveCurrentWithName(ext.getDestination() + TFile.separator 
                                + (tabPan.fileName.trim().endsWith(".man") ? 
                                tabPan.fileName.trim().substring(0, tabPan.fileName.lastIndexOf("."))
                                : tabPan.fileName) + ext.getExtension());
                    }
                }
            };
            th.start();
        }
    }
    /**
     * Saves all the currently open management files as templates.
     */
    @Override
    public void saveAllAsTemplate()
    {
        if(EventQueue.isDispatchThread())
        {
            Thread th = new Thread()
            {
                @Override
                public void run()
                {
                    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);
                    ExtensionSelector ext = new ExtensionSelector(dirXML.getAbsolutePath());
                    if(!ext.recieveInput())  return; 
                    for(int index = 0; index < timelineObject.getNumFiles(); index ++)
                    {
                        TablePanel tabPan = timelineObject.getTablePanelNoSelect(index);
                        tabPan.saveCurrentWithName(ext.getDestination() + TFile.separator 
                                + (tabPan.fileName.trim().endsWith(".man") ? 
                                tabPan.fileName.trim().substring(0, tabPan.fileName.lastIndexOf("."))
                                : tabPan.fileName) + ext.getExtension());
                    }
                }
            };
            th.start();
        }
    }
    /**
     * Allows the user to select the file they want to open, etc. using a file
     * chooser.
     * @return 
     */
    public String findFile(String path)
    {
        WepsFileChooser mfc;
        if(cd.isFormatXMLAllowed())
        {
            mfc = WepsFileChooser.create(WepsFileChooser.Action.Select, 
                    new TFile(path), false, true, null,
                    WepsFileTypes.Management, WepsFileTypes.Rotation, WepsFileTypes.XML);
        }
        else
        {
            mfc = WepsFileChooser.create(WepsFileChooser.Action.Select, 
                    new TFile(path), false, true, null,
                    WepsFileTypes.Management, WepsFileTypes.Rotation);
        }
        //set the tooltip of "home" button to "Home" instead of "Desktop"
        mfc.homeToolTip(mfc);
        //remove the NewFolder button
        mfc.disableNewFolder(mfc);
//        if ((tableObject.getSavePath() == null) || (tableObject.getSavePath().length()
//                == 0)) mfc.setCurrentDirectory(new TFile(MCREWConfig.getDirectoryName(
//                            XMLConstants.smanagement_template)));
//        else mfc.setCurrentDirectory(new TFile(tableObject.getSavePath()));
        mfc.setCurrentDirectory(new TFile(path));
        if (!(mfc.showDialog(this) == WepsFileChooser.APPROVE_OPTION)) {
            return null;
        }
        
        return (new TFile(mfc.getSelectedFile())).getAbsolutePath();
    }
    
    /**
     * Overriden so as to force a call to repaint the timeline, as the timeline
     * won't paint unless repaint is called. 
     */
    @Override
    public void repaint()
    {
        super.repaint();
        if(timelineObject != null) timelineObject.repaint();
    }
    
    /**
     * Initializes the view menu.
     */
    private void setupViews()
    {
        for (final MCREWConfig.TableView view : MCREWConfig.getTableViews()) {
            //The default view is a special case and hardcoded into the menus
            if (view.getName().equals("default")) {
                continue;
            }
            JCheckBoxMenuItem cmi = null;
            JToggleButton tb = null;

            if (view.getMenuText() != null && view.getMenuText().length() > 0) {
                cmi = new JCheckBoxMenuItem(view.getMenuText());
                JM_view.add(cmi);
                tableObject.addCmis(view.getName(), cmi);
            }

            if (view.getToolbarImage() != null && view.getToolbarImage().length() > 0) {

                addToggleButton(new ImageIcon(Resources.getImage(view.getToolbarImage())), view.getName());
                tb = new JToggleButton();
            }

            if (cmi != null || tb != null) {
                //It is gui
                c_guiViews.add(view.getName());
            }

            final JCheckBoxMenuItem cmi2 = cmi;
            final JToggleButton tb2 = tb;

            if (cmi != null) {
                cmi.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        tableObject.handleViewToggle(view.getName(), cmi2.isSelected());
                    }
                });
            }

            if (tb != null) {
                tb.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        tableObject.handleViewToggle(view.getName(), tb2.isSelected());
                    }
                });
            }

        }
    }
    
    /**
     * Adds the specific toggle button to the button bar of the table.
     * @param icon
     * @param name 
     */
    private void addToggleButton(ImageIcon icon, String name)
    {
        for(int index = 0; index < timelineObject.getNumFiles(); index ++)
        {
            JToggleButton tb = new JToggleButton(icon);
            timelineObject.getTablePanelNoSelect(index).addtoToolbar(tb);
            timelineObject.getTablePanelNoSelect(index).addTbs(name, tb);
            tb.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    tableObject.handleViewToggle(name, tb.isSelected());
                }
            });
        }
    }
    
    /**
     * Attaches the necessary help to relevant fields in the coordinator and fires
     * the add help in the subcomponents of MCREW (Table and Timeline).
     */
    private void addHelp() {
        //If the mcrew helpset has already been loaded we can skip this.
        if (Help.hasHelpSet("MCREW") == false) {
            loadHelp();
        }

        addCSH(Help.getHelpSet());
    } //end of addhelp()

    /**
     * Attempts all valid options for finding the help jar.  
     */
    private void loadHelp() {
        //Possible locations for the mcrew help files.
        String jarFilePath = "jar/MasterHelp.jar";
        String mcrewJarPath = "jar/McrewHelp.jar";
        String dirFilePath = "help/mcrew1/mcrew.hs";

        if (Help.loadJar(jarFilePath, "mcrew1/mcrew.hs")) {
        } else if (Help.loadJar(mcrewJarPath)) {
        } else if (Help.loadDirectory(dirFilePath)) {
        }
    }
    
    /**
     * Adds help to the frame.
     * @param hs_mcrew 
     */
    private void addCSH(HelpSet hs_mcrew) 
    {
        hb_mcrew = hs_mcrew.createHelpBroker();
        //hb_mcrew = hs_mcrew.getHelpBroker();
        hb_mcrew.enableHelpKey(getRootPane(), "McrewIntro_html", hs_mcrew);
        hb_mcrew.enableHelpOnButton(JMI_help, "McrewIntro_html", hs_mcrew);
        hb_mcrew.enableHelpOnButton(aboutButton, "introduction_html", hs_mcrew);
        ActionListener helper = new CSH.DisplayHelpFromSource(hb_mcrew);

        ////System.out.println("I am in the WEPS addHelp()" + helper);
        JMI_help.addActionListener(helper);
        //contextsensitive help
        helpButton.addActionListener(new CSH.DisplayHelpAfterTracking(hs_mcrew, "javax.help.Popup", null));
        CSH.setHelpIDString(JS_bar, "mcrewMenuBar_html");//FIXME
        CSH.setHelpIDString(JM_fileOld, "mcrewMenuFile_html");
        CSH.setHelpIDString(JM_edit, "mcrewMenuEdit_html");
        CSH.setHelpIDString(JM_view, "mcrewMenuView_html");
        CSH.setHelpIDString(JM_configure, "mcrewMenuConfigure_html");
        CSH.setHelpIDString(JM_tools, "mcrewMenuTools_html");
        CSH.setHelpIDString(JM_help, "mcrewMenuHelp_html");
        CSH.setHelpIDString(JMB_main, "mcrewMenuBar_html");
        CSH.setHelpIDString(aboutButton, "mcrewHelpButton_html");
        CSH.setHelpIDString(helpButton, "mcrewInfoButton_html");
        CSH.setHelpIDString(JB_close, "mcrewCloseButton_html");
        tableObject.addCSH(hs_mcrew);
        timelineObject.addCSH(hs_mcrew);
    } //end of addCSH
    
    /**
     * Iterates over every table in the timeline, loading each table that has been
     * changed into view and prompting the user asking if they wish to save said
     * table.
     * @return 
     */
    @SuppressWarnings("fallthrough")
    private boolean checkandSaveAll()
    {
        boolean saveSuccess = true;
        boolean continued = true;
        for(int index = 0; index < timelineObject.getNumFiles(); index ++)
        {
            TablePanel tempTable = timelineObject.getTablePanelNoSelect(index);
            if(tempTable.table.getDataChanged()) refocus(index);
            else continue;
            if (tableObject.table.getDataChanged()) {
                int option = JOptionPane.showConfirmDialog(this, "Save current Management File?");
                switch (option) {
                    case JOptionPane.CANCEL_OPTION:
                        this.setVisible(true);
                        continued &=  false;
                        break;
                    case JOptionPane.YES_OPTION:
                        if (!tableObject.table.checkAllConditions()) saveSuccess &= false;
                        if ((tableObject.fileName == null) || (tableObject.fileName.
                                length() == 0) || (tableObject.fileName.equals(
                                TablePanel.sUntitledFileName))) saveCurrentAs();
                        else saveCurrent();
                        saveSuccess &= tableObject.saveSuccess;
                        break;
                    case JOptionPane.NO_OPTION:
                        break;
                }
            }
        }
        return saveSuccess && continued;
    }
    /**
     * Iterates through all the tables in the timeline and clears all of the data
     * contained within them to free up memory.
     */
    public void clearAndDispose()
    {
        for(int index = 0; index < timelineObject.getNumFiles(); index ++)
        {
            TablePanel tempTable = timelineObject.getTablePanelNoSelect(index);
            tempTable.cleanup();
        }
    }
    
    /**
     * Receives a data changed event, and increments or decrements the counter for
     * number of tables changed based on true or false.
     * @param input 
     */
    public void dataChange(boolean input) { int res = input ? dataChanged ++ : dataChanged --; }
    /**
     * Passes the waiting event to the proper table.
     * @param input 
     */
    public void setWaiting(boolean input) { tableObject.setWaiting(input); }
    /**
     * Returns the label state of the active table.
     * @return 
     */
    public boolean getLabelState() { return tableObject.getLabelState(); }
    /**
     * Returns the absolute path to the file currently open in the table that
     * currently holds focus.
     * @return 
     */
    public String getAbsoluteFileName() { return tableObject.absFileName; }
    /**
     * Returns the name of the file currently open in the table that currently 
     * holds focus.
     * @return 
     */
    public String getFileName() { return tableObject.fileName; } 
    
    /**
     * Makes visible/invisible all components which only exist in full timeline
     * mode or only in single file mode, moves components to their proper location
     * that are shared between the two.
     */
    private void singleFileMode()
    {
        //Set all timeline components invisible.
        JM_file.setVisible(false);
        JM_fileOld.setVisible(true);
        timelineContainer.setVisible(false);
        JP_toolBar.setVisible(false);
        
        //Move necessary buttons back to MCREW.
        tableObject.JTB_main.add(aboutButton);
        tableObject.JTB_main.add(helpButton);
        tableObject.JTB_main.add(JB_close);
        JM_fileOld.add(JMI_print);
        JM_fileOld.add(JMI_exit);
    }
    
    /**
     * Receives date changes, and fire a repaint for both the table and the timeline,
     * as the date change is the only operation that will significantly affect
     * both the table and the timeline.
     */
    public void dateChange(Object origin)
    {
        if((origin instanceof TimelinePanel))
        {
            if(MCREWConfig.autosort) 
            {
                for(int index = 0; index < timelineObject.getNumFiles(); index ++)
                {
                    timelineObject.getTablePanelNoSelect(index).SortJMI_actionPerformed(null);
                }
            }
        }
        else
        {
            timelineObject.recalibrateDates();
        }
        timelineObject.repaint();
        tableObject.repaint();
    }
    
    /**
     * Passes the table the given property change listener, so that events will
     * be properly relayed between MCREW and WEPS.
     * @param l 
     */
    @Override
    public void addPropertyChangeListener(PropertyChangeListener l) 
    { 
        for(int index = 0; index < timelineObject.getNumFiles(); index ++)
        {
            timelineObject.getTablePanelNoSelect(index).addPropertyChangeListener(l);
        }
    }
    
    
    /**
     * 
     * @param evt 
     */
    @Override
    protected void SkelToManRec_actionPerformed(ActionEvent evt)
    {
        if(sMC == null) sMC = new SkelManConverter(this);
        sMC.SkelToManRec_actionPerformed(evt);
    }
    /**
     * 
     * @param evt 
     */
    @Override
    protected void ManToSkelRec_actionPerformed(ActionEvent evt)
    {
        if(sMC == null) sMC = new SkelManConverter(this);
        sMC.ManToSkelRec(evt);
    }
    /**
     * 
     * @param evt
     * @param singleFileOnly 
     */
    @Override
    protected void ManToSkelJMI_actionPerformed(ActionEvent evt, boolean singleFileOnly)
    {
        if(sMC == null) sMC = new SkelManConverter(this);
        sMC.ManToSkel(evt, singleFileOnly);
    }
    /**
     * 
     * @param evt
     * @param singleFileOnly 
     */
    @Override
    protected void SkelToManJMI_actionPerformed(ActionEvent evt, boolean singleFileOnly)
    {
        if(sMC == null) sMC = new SkelManConverter(this);
        sMC.SkelToMan(evt, singleFileOnly);
    }
}
