/******************************************************************************
* Copyright 1996-2014 United States Government as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All Rights Reserved.
******************************************************************************/

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import javax.swing.*; 
import java.awt.datatransfer.*;

/** SkeletonTable produces a skeleton table from a CDF. A skeleton table is 
    a text file which can be read by the SkeletonCDF program to build a 
    skeleton CDF.
 */

public class SkeletonTable extends JFrame 
			    implements ActionListener, ItemListener, 
				       MouseListener, FocusListener, Runnable { 

    static final long serialVersionUID = 1L;
    static int macLib = 0;
    static String cdfbase = null;
    static String libcdfPath = null;

    JFrame parentDriver;
/** The dialog for user interface. */
    JDialog dialog;
    JPanel panelx = new JPanel(new BorderLayout(), true);

/** The FileChooser for the file selection. */
    JFileChooser fileChooser = new JFileChooser();

/** The panel for text fields and selectable buttons which goes to dialog's
    north portion. */
    JPanel panel1 = new JPanel(new GridBagLayout(), true);
/** The panel containing all checkboxes goes to dialog's center portion. */
    JPanel panel2 = new JPanel(new BorderLayout(), true);
    JPanel panel2n = new JPanel(new GridBagLayout(), true);
    JPanel panel2c = new JPanel(new GridBagLayout(), true);
    JPanel panel2s = new JPanel(new GridBagLayout(), true);
/** The panel containing panel31 and text area goes to dialog's south portion. */
    JPanel panel3 = new JPanel(new BorderLayout(), true);
    JPanel panel31 = new JPanel(new GridLayout(1, 3, 50, 20), true);
    JPanel tpanel1 = new JPanel(new BorderLayout(), true);
    JPanel tpanel2 = new JPanel(new BorderLayout(), true);
    JPanel tpanel3 = new JPanel(new BorderLayout(), true);
    JPanel tpanel4 = new JPanel(new BorderLayout(), true);

/** "Page Output" checkbox. */
    JCheckBox pgc = new JCheckBox("Page Output", false);
/** "Use Format" checkbox. */
    JCheckBox ufc = new JCheckBox("Use Format", false);
/** "Report Info's" checkbox. */
    JCheckBox ric = new JCheckBox("Report Info's");
    int ricX = 0;
/** "Report Warnings" checkbox. */
    JCheckBox rwc = new JCheckBox("Report Warnings", true);
    int rwcX = 1;
/** "Report Errors" checkbox. */
    JCheckBox rec = new JCheckBox("Report Errors", true);
    int recX = 1;
/** "-0.0 to 0.0" checkbox. */
    JCheckBox zzc = new JCheckBox("-0.0 to 0.0");
/** "Display Statistics" checkbox. */
    JCheckBox dsc = new JCheckBox("Display Statistics");
    int dscX = 0;
/** "Output to Screen" checkbox. */
    JCheckBox osc = new JCheckBox("Output to Screen");
    int oscX = 0;
/** "Log Progress" checkbox. */
    JCheckBox lpc = new JCheckBox("Log Progress");
    int lpcX = 0;
/** "About" checkbox. */
    JCheckBox abc = new JCheckBox("About");
/** "Run it Batch" checkbox. */
    JCheckBox bac = new JCheckBox("Run it Batch", false);

/** A group radio buttons for zMode. */
    ButtonGroup zmode = new ButtonGroup();
/** A group radio buttons for zMode. */
    JRadioButton zmode0 = new JRadioButton("Off");
    JRadioButton zmode1 = new JRadioButton("On/1");
    JRadioButton zmode2 = new JRadioButton("On/2");
/** A radio button panel for zMode. */
    JPanel zmodePanel = new JPanel(true);

/** A group radio buttons for Style. */
    ButtonGroup style = new ButtonGroup();
/** A group radio buttons for style. */
    JRadioButton style0 = new JRadioButton("Style/0");
    JRadioButton style1 = new JRadioButton("Style/1");
    JRadioButton style2 = new JRadioButton("Style/2");
    JRadioButton style3 = new JRadioButton("Style/3");
    JRadioButton style4 = new JRadioButton("Style/4");
/** A radio button panel for style. */
    JPanel stylePanel = new JPanel(true);

/** A group radio buttons for AdvFormat. */
    ButtonGroup newformat = new ButtonGroup();
/** A group radio buttons for newformat. */
    JRadioButton newformat0 = new JRadioButton("best");
    JRadioButton newformat1 = new JRadioButton("no");
    JRadioButton newformat2 = new JRadioButton("metaonly");
    JRadioButton newformat3 = new JRadioButton("dataonly");
    JRadioButton newformat4 = new JRadioButton("all");
/** A radio button panel for newformat. */
    JPanel newformatPanel = new JPanel(true);

/** A group radio buttons for Values. */
    ButtonGroup values = new ButtonGroup();
/** A group radio buttons for Values. */
    JRadioButton values0 = new JRadioButton("None");
    JRadioButton values1 = new JRadioButton("NRV");
    JRadioButton values2 = new JRadioButton("RV");
    JRadioButton values3 = new JRadioButton("All");
    JRadioButton values4 = new JRadioButton("Selected");
/** A radio button panel for Values. */
    JPanel valuesPanel = new JPanel(true);

/** "Enter" button. */
    JButton entrb = new JButton(" Enter ");
/** "Help" button. */
    JButton helpb = new JButton(" Help ");
/** "Quit" button. */
    JButton quitb = new JButton(" Quit ");
/** "Select1" button for selecting the source CDF file. */
    JButton slt1 = new JButton("Select");
/** "Select2" button for selecting the destination skeleton table file. */
    JButton slt2 = new JButton("Select");

/** Text area for information. */
    JTextArea info = new JTextArea(20,40);

/** Text field for entering optional cache sizes. */
    JTextField cachesizes = new JTextField("",40);
/** Text field for entering optionally selected variables. */
    JTextField variables = new JTextField("",40);
/** Text field for entering the mandatory source CDF file name. */
    JTextField cdf = new JTextField("", 40);
/** Text field for entering optional destination skeleton table file name. */
    JTextField sklt = new JTextField("", 40);

/** A label of "CDF:" for the text field cdf. */
    JLabel CDF = new JLabel("CDF: ");
/** A label of "Skeleton:" for the text field sklt. */
    JLabel SKLT = new JLabel("Skeleton: ");
/** A label of "Cache Sizes:" for the text field cachesizes. */
    JLabel CASS = new JLabel("Cache Sizes: ");
/** A label of "Variables:" for the text field variables. */
    JLabel VARB = new JLabel("Variables: ");
/** A label of "zMode:" for the radio button group zmode. */
    JLabel ZMODE = new JLabel("zMode: ");
/** A label of "Style:" for the radio button group zmode. */
    JLabel STYLE = new JLabel("Style: ");
/** A label of "AdvFormat::" for the radio button group zmode. */
    JLabel NEWFORMAT = new JLabel("AdvFormat: ");
/** A label of "Values:" for the radio button group values. */
    JLabel VALUES = new JLabel("Values: ");

/** Scroll pane for the text area. */
    JScrollPane scroller;

/** Hold valid extensions for the CDF files for the file chooser. */
    String[] cdfs = {"cdf", "CDF"};
/** Hold valid extensions for the skeleton table files for the file chooser. */
    String[] sklts = {"skt", "SKT"};
/** A file filter for CDF files for the file chooser. */
    SimpleFileFilter filter1 = new SimpleFileFilter(cdfs, 
						" CDF files (*.cdf, *.CDF)");
/** A file filter for skeleton table files for the file chooser. */
    SimpleFileFilter filter2 = new SimpleFileFilter(sklts,
						" skeleton tables (*.skt, *.SKT)");

/** The command string. */
    String command = "skeletontable ";
    String commandX;
    String[] cmds = new String[3];

/** Environment variable for the current directory. */
    String currentdir = System.getProperty("user.dir");
/** The file separator. */
    String separator = System.getProperty("file.separator");
/** Valid values for radion buttons for values. */
    String[] valuesy = {"none", "nrv", "rv", "all", "???"};
    String strpo = "-nopage ";
    String struf = "-format ";
    String strva = "";
    String strri = "";
    String strrw = "w";
    String strre = "e";
    String strds = " ";
    String stros = "";
    String strlp = " ";
    String strzz = " ";
    String strzm = "";
    String strsty = "";
    String strnfm = "";
    String report, Zmode, caches, temp, vars, estyle, enewformat;
    String cdfspec = " ";
    String skltspec = "";
    String SKLTfile;
    String Values = " ";
    String Caches = " ";
    String cdfDelimiter, sktDelimiter;
/** A platform-dependent Runtime object. */
    Runtime runtime = Runtime.getRuntime();
/** A separate process to run the command. */
    Process process = null;
    int hlp = 0;
    int abcX = 0;
    int iba = 0;

/** The text field is currently getting the focus. */
    JTextField focused = null;
/** The text field previously was focused. */
    JTextField prevfocused = null;
/** Menu bar. */
    JMenuBar menuBar = new JMenuBar();
/** A menu: File. */
    JMenu menuFile = new JMenu("File");
/** A menu: Edit. */
    JMenu menuEdit = new JMenu("Edit");
/** A menu: Help. */
    JMenu menuHelp = new JMenu("Help");
/** An Edit menu item: Copy. */
    JMenuItem menuEditCopy = new JMenuItem("Copy");
/** An Edit menu item: Cut. */
    JMenuItem menuEditCut = new JMenuItem("Cut");
/** An Edit menu item: Paste. */
    JMenuItem menuEditPaste = new JMenuItem("Paste");
/** A File menu item: Exit. */
    JMenuItem menuFileExit = new JMenuItem("Exit");
/** A Help menu item: Help. */
    JMenuItem menuHelpHelp = new JMenuItem("Help");
    int istart = -1;
    int iend = -1;

    Dimension hpad5 = new Dimension(5,1);
    Dimension hpad10 = new Dimension(10,1);
    Dimension hpad20 = new Dimension(20,1);
    Dimension hpad25 = new Dimension(25,1);
    Dimension hpad30 = new Dimension(30,1);
    Dimension hpad40 = new Dimension(40,1);
    Dimension hpad80 = new Dimension(80,1);
    Dimension hpad120 = new Dimension(120,1);
    Dimension vpad5 = new Dimension(1,5);
    Dimension vpad10 = new Dimension(1,10);
    Dimension vpad20 = new Dimension(1,20);
    Dimension vpad25 = new Dimension(1,25);
    Dimension vpad30 = new Dimension(1,30);
    Dimension vpad40 = new Dimension(1,40);
    Dimension vpad80 = new Dimension(1,80);

    Font  defaultFont = new Font("Dialog", Font.PLAIN, 12);
    Font  boldFont = new Font("Dialog", Font.BOLD, 12);
    Font  bigFont = new Font("Dialog", Font.PLAIN, 18);
    Font  bigboldFont = new Font("Dialog", Font.BOLD, 18);
    static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    static int INITIAL_WIDTH = 600;
    static int INITIAL_HEIGHT = 400;

/** The default dialog modal (is set to false). */
    static boolean defaultModal = false;
    static String  defaultfname = "";
    static File    defaultfile  = null;
/** The current dialog modal. */
    boolean modal;
    int frommain = 0;

    SkeletonTable() {
        this(null, null, defaultModal);
    }

    SkeletonTable(JFrame parentDriver) {
        this(parentDriver, null, defaultModal);
    }

    SkeletonTable(JFrame parentDriver, String cdfbase) {
        this(parentDriver, cdfbase, defaultModal);
    }

    SkeletonTable(JFrame parentDriver, String cdfbase, boolean modal) {
        if (cdfbase == null) {
          cdfbase = System.getProperty("CDF_BASE");
          if (cdfbase == null)
            cdfbase = CDFToolsUtil.getenv("CDF_BASE");
        }
        if (cdfbase != null)
          command = cdfbase + separator + "bin" + separator + "skeletontable ";
        else
          command = "skeletontable ";

	dialog = new JDialog(this, modal);
	this.parentDriver = parentDriver;
	this.modal = modal;
    }
/*
    SkeletonTable(JFrame parentDriver) {
	this(parentDriver, defaultModal, defaultfname, defaultfile);
    }


    SkeletonTable(JFrame parentDriver, boolean modal) {
	this(parentDriver, modal, defaultfname, defaultfile);
    }


    SkeletonTable(JFrame parentDriver, boolean modal, String fname) {
	this(parentDriver, modal, fname, defaultfile);
    }

    SkeletonTable(JFrame parentDriver, boolean modal, String fname, File afile) {
	super(parentDriver, modal);
	dialog = this;
	this.modal = modal;
	if (fname != null) cdf.setText(fname);
    }
*/

/** Set up the GUI stuff for user selection.
 */

    private void buildGUI() {

        WindowListener l = new WindowAdapter() {
           public void windowClosing(WindowEvent e) {
	      if (macLib == 1) new File(libcdfPath).delete();
              if (frommain == 0) {
		if (modal) dialog.dispose();
		else dialog.setVisible(false);
		if (parentDriver != null) parentDriver.setVisible(true);
              } else {
		System.exit(1);
	      }
	   }
        };
        dialog.addWindowListener(l);
        dialog.setTitle("Enter   Parameters/qualifiers  for  SkeletonTable");
        dialog.setSize(INITIAL_WIDTH, INITIAL_HEIGHT);
        dialog.setLocation(screenSize.width/2 - INITIAL_WIDTH/2,
                          screenSize.height/2 - INITIAL_HEIGHT/2);
        dialog.getContentPane().setLayout(new BorderLayout());
	
        // set the menu bar
        dialog.setJMenuBar(menuBar);

        // add the file menu
        menuBar.add(menuFile);

        // add the menu items to file
        menuFile.add(menuFileExit);
        menuFileExit.addActionListener(this);

        // add the edit menu
        menuBar.add(menuEdit);

        // add the menu items to edit
        menuEdit.add(menuEditCopy);
        menuEdit.add(menuEditCut);
        menuEdit.add(menuEditPaste);
        menuEditCopy.addActionListener(this);
        menuEditCut.addActionListener(this);
        menuEditPaste.addActionListener(this);

        // add the help menu
        menuBar.add(menuHelp);

        // add the menu items to help
        menuHelp.add(menuHelpHelp);
        menuHelpHelp.addActionListener(this);

        // Panel 1

        makeJButton(panel1, Box.createRigidArea(vpad5), 0, 0, 1, 1, 1.0, 1.0);
	makeJButton(panel1, CDF,  0, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel1, cdf,  1, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel1, slt1, 2, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel1, SKLT, 0, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel1, sklt, 1, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel1, slt2, 2, 2, 1, 1, 1.0, 1.0);
	makeJButton(panel1, Box.createRigidArea(vpad10), 0, 3, 1, 1, 1.0, 1.0);
        cdf.addActionListener(this);
        cdf.addFocusListener(this);
        cdf.addMouseListener(this);
        cdf.setToolTipText("Enter the source CDF (without extension) ");
        sklt.addActionListener(this);
        sklt.addFocusListener(this);
        sklt.addMouseListener(this);
        sklt.setToolTipText("Enter the destination skeleton table  (without extension) to be created");
        slt1.addActionListener(this);
        slt1.setToolTipText("Use the file chooser to select the source CDF");
        slt2.addActionListener(this);
        slt2.setToolTipText("Use the file chooser to select the destination skeleton table");
	CDF.setFont(boldFont);
	cdf.setFont(boldFont);
	SKLT.setFont(boldFont);
  	sklt.setFont(boldFont);
//	dialog.getContentPane().add(panel1,BorderLayout.NORTH);
	panelx.add(panel1,BorderLayout.NORTH);
	
        // Panel 2

        // Initialize the zMode choice.

        ZModeListener zModeListener = new ZModeListener();
        zmode0.setActionCommand("0");
        zmode1.setActionCommand("1");
        zmode2.setActionCommand("2");
        zmode0.addActionListener(zModeListener);
        zmode1.addActionListener(zModeListener);
        zmode2.addActionListener(zModeListener);
        zmode0.setSelected(true);
        zmode.add(zmode0);
        zmode.add(zmode1);
        zmode.add(zmode2);
        zmode0.setToolTipText("Use variables as-is from the CDF for the skeleton table");
        zmode1.setToolTipText("Use zMode/1 for variables from the CDF for the skeleton table");
        zmode2.setToolTipText("Use zMode/2 for variables from the CDF for the skeleton table");

        zmodePanel.setLayout(new FlowLayout());
        zmodePanel.add(zmode0);
        zmodePanel.add(zmode1);
        zmodePanel.add(zmode2);
	
        // Initialize the Style choice.

        StyleListener styleListener = new StyleListener();
        style0.setActionCommand("0");
        style1.setActionCommand("1");
        style2.setActionCommand("2");
        style3.setActionCommand("3");
        style4.setActionCommand("6");
        style0.addActionListener(styleListener);
        style1.addActionListener(styleListener);
        style2.addActionListener(styleListener);
        style3.addActionListener(styleListener);
        style4.addActionListener(styleListener);
        style4.setSelected(true);
        style.add(style0);
        style.add(style1);
        style.add(style2);
        style.add(style3);
        style.add(style4);
        style0.setToolTipText("Use dd-mom-yyyy hh:mm-ss.mmm for CDF_EPOCH and dd-mom-yyyy hh:mm-ss.mmm.uuu.nnn.ppp for CDF_EPOCH16");
        style1.setToolTipText("Use yyyymmdd.ttttttt for CDF_EPOCH and yyyymmdd.ttttttttttttttt for CDF_EPOCH16");
        style2.setToolTipText("Use yyyymmddhhmnss for both CDF_EPOCH and CDF_EPOCH16");
        style3.setToolTipText("Use yyyy-mm-ddThh:mn:ss.mmmZ for CDF_EPOCH and yyyy-mm-ddThh:mn:ss.mmm.uuu.nnn.pppZ for CDF_EPOCH16");
        style4.setToolTipText("Use yyyy-mm-ddThh:mn:ss.mmm for CDF_EPOCH or yyyy-mm-ddThh:mn:ss.mmmuuunnnppp CDF_EPOCH16");

        stylePanel.setLayout(new FlowLayout());
        stylePanel.add(style0);
        stylePanel.add(style1);
        stylePanel.add(style2);
        stylePanel.add(style3);
        stylePanel.add(style4);
	
        // Initialize the AdvFormat choice.

        AdvFormatListener newformatListener = new AdvFormatListener();
        newformat0.setActionCommand("best");
        newformat1.setActionCommand("no");
        newformat2.setActionCommand("metaonly");
        newformat3.setActionCommand("dataonly");
        newformat4.setActionCommand("all");
        newformat0.addActionListener(newformatListener);
        newformat1.addActionListener(newformatListener);
        newformat2.addActionListener(newformatListener);
        newformat3.addActionListener(newformatListener);
        newformat4.addActionListener(newformatListener);
        newformat0.setSelected(true);
        newformat.add(newformat0);
        newformat.add(newformat1);
        newformat.add(newformat2);
        newformat.add(newformat3);
        newformat.add(newformat4);
        newformat4.setToolTipText("Use variable's FORMAT attribute to encode metadata and data value -- supersede the \"Use Format\" checkbox.");
        newformat1.setToolTipText("Not to use variable's FORMAT attribute to encode metadata and data value -- supersede the \"Use Format\" checkbox.");
        newformat2.setToolTipText("Use variable's FORMAT attribute to encode only metadata -- supersede the \"Use Format\" checkbox.");
        newformat3.setToolTipText("Use variable's FORMAT attribute to encode variable data only -- supersede the \"Use Format\" checkbox.");
        newformat0.setToolTipText("Use the best format, higher precision, either from variable's FORMAT attribute or C's %g to encode metadata and data -- supersede the \"Use Format\" checkbox.");

        newformatPanel.setLayout(new FlowLayout());
        newformatPanel.add(newformat0);
        newformatPanel.add(newformat1);
        newformatPanel.add(newformat2);
        newformatPanel.add(newformat3);
        newformatPanel.add(newformat4);
	
	// Initialize the values choice.

        ValuesListener valuesListener = new ValuesListener();
        values0.setActionCommand("none");
        values1.setActionCommand("nrv");
        values2.setActionCommand("rv");
        values3.setActionCommand("all");
        values4.setActionCommand("???");
        values0.addActionListener(valuesListener);
        values1.addActionListener(valuesListener);
        values2.addActionListener(valuesListener);
        values3.addActionListener(valuesListener);
        values4.addActionListener(valuesListener);
        values1.setSelected(true);
        values.add(values0);
        values.add(values1);
        values.add(values2);
        values.add(values3);
        values.add(values4);
        values0.setToolTipText("No variable data will be placed in the skeleton table");
        values1.setToolTipText("Only non-record variant variable data will be placed in the skeleton table"); 
        values2.setToolTipText("Only variant record variable data will be placed in the skeleton table");  
        values3.setToolTipText("All data will be placed in the skeleton table"); 
        values4.setToolTipText("Only selected variables's data will be placed in the skeleton table"); 
        valuesPanel.setLayout(new FlowLayout());
        valuesPanel.add(values0);
        valuesPanel.add(values1);
        valuesPanel.add(values2);
        valuesPanel.add(values3);
        valuesPanel.add(values4);
	
	makeJButton(panel2n, osc, 0, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, Box.createRigidArea(hpad40), 1, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, ric, 2, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, Box.createRigidArea(hpad40), 3, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, pgc, 4, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, ufc, 0, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, Box.createRigidArea(hpad40), 1, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, rwc, 2, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, Box.createRigidArea(hpad40), 3, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, dsc, 4, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, zzc, 0, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, Box.createRigidArea(hpad40), 1, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, rec, 2, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, Box.createRigidArea(hpad40), 3, 2, 1, 1, 1.0, 1.0);
//        makeJButton(panel2n, bac, 4, 2, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, lpc, 0, 3, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, Box.createRigidArea(hpad40), 1, 3, 1, 1, 1.0, 1.0);
        makeJButton(panel2n, abc, 2, 3, 1, 1, 1.0, 1.0);
        tpanel1.add(ZMODE,BorderLayout.WEST); 
	tpanel1.add(zmodePanel, BorderLayout.CENTER);
	makeJButton(panel2n, tpanel1, 4, 3, 1, 1, 1.0, 1.0);
        tpanel2.add(STYLE,BorderLayout.WEST);
        tpanel2.add(stylePanel, BorderLayout.CENTER);

        tpanel3.add(NEWFORMAT,BorderLayout.WEST);
        tpanel3.add(newformatPanel, BorderLayout.CENTER);

        tpanel4.add(VALUES, BorderLayout.WEST); 
        tpanel4.add(valuesPanel, BorderLayout.CENTER);
//        makeJButton(panel2c, Box.createRigidArea(hpad10), 1, 0, 1, 1, 1.0, 1.0);
	makeJButton(panel2c, tpanel2, 0, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2c, Box.createRigidArea(vpad10), 1, 0, 1, 1, 1.0, 1.0);
	makeJButton(panel2c, tpanel4, 2, 0, 1, 1, 1.0, 1.0);
	makeJButton(panel2c, Box.createRigidArea(vpad10), 3, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2c, tpanel3, 0, 1, 1, 1, 1.0, 1.0);

//        makeJButton(panel2c, Box.createRigidArea(vpad10), 0, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2s, CASS, 0, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2s, cachesizes, 1, 0, 2, 1, 1.0, 1.0);
        makeJButton(panel2s, Box.createRigidArea(hpad40), 2, 0, 1, 1, 1.0, 1.0);
        makeJButton(panel2s, VARB, 0, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2s, variables, 1, 1, 2, 1, 1.0, 1.0);
        makeJButton(panel2s, Box.createRigidArea(hpad40), 2, 1, 1, 1, 1.0, 1.0);
        makeJButton(panel2s, Box.createRigidArea(vpad20), 0, 2, 1, 1, 1.0, 1.0);
	panel2.add(panel2n, BorderLayout.NORTH);
        panel2.add(panel2c, BorderLayout.CENTER);
	panel2.add(panel2s, BorderLayout.SOUTH);
	ZMODE.setFont(boldFont);
	STYLE.setFont(boldFont);
	NEWFORMAT.setFont(boldFont);
	VALUES.setFont(boldFont);
	CASS.setFont(boldFont);
	cachesizes.setFont(boldFont);
	VARB.setFont(boldFont);
	variables.setFont(boldFont);

	pgc.addItemListener(this);
        pgc.setToolTipText("Select to display the output one page at a time -- not avaiable for Java");
        ric.addItemListener(this);
        ric.setToolTipText("Select to report informational messages from the CDF library calls");
        osc.addItemListener(this);
	osc.setToolTipText("Select to output the skeleton table to the screen");
        rwc.addItemListener(this);
        rwc.setToolTipText("Select to report warning messages from the CDF library calls");
        lpc.addItemListener(this);
        lpc.setToolTipText("Select to display the progress");
        rec.addItemListener(this);
        rec.setToolTipText("Select to report error messages from the CDF library calls");
        dsc.addItemListener(this);
        dsc.setToolTipText("Select to display caching statistics after run");
        ufc.addItemListener(this);
        ufc.setToolTipText("Select to use FORMAT attribute entry for each variable");
        zzc.addItemListener(this);
        zzc.setToolTipText("Select to convert -0.0 to 0.0");
	abc.addItemListener(this);
        abc.setToolTipText("Display the current version");
	bac.addItemListener(this);
        bac.setToolTipText("Select to set up and run the SkeletonTable by a batch job");
        cachesizes.addActionListener(this);
        cachesizes.addFocusListener(this);
        cachesizes.addMouseListener(this);
        cachesizes.setToolTipText("Enter the cache sizes for dotCDF, staging and compression scratch files in 512 bytes buffer");
        variables.addActionListener(this);
        variables.addFocusListener(this);
        variables.addMouseListener(this);
        variables.setToolTipText("Enter comma-separated list of delimited variable names for selected variables"); 

//        dialog.getContentPane().add(panel2,BorderLayout.CENTER);
        panelx.add(panel2,BorderLayout.CENTER);

        // Panel 3 (buttons and text area)

        panel31.add(entrb);
        panel31.add(helpb);
        panel31.add(quitb);
  	panel3.add(panel31, BorderLayout.NORTH);
        panel3.add(Box.createRigidArea(vpad30),BorderLayout.CENTER);

        // Listen for events on buttons
        entrb.addActionListener(this);
        entrb.setToolTipText("Run SkeletonTable");
        helpb.addActionListener(this);
        helpb.setToolTipText("Get the complete help information");
        quitb.addActionListener(this);
        quitb.setToolTipText("Exit SkeletonTable");

	// Text Area
  	info.setEditable(false);
  	scroller = new JScrollPane() {
                static final long serialVersionUID = 1L;

		public Dimension getPreferredSize() {
		   return new Dimension(80, 160);
		}
		public float getAlignmentX() {
		   return LEFT_ALIGNMENT;
		}
	};
	scroller.getViewport().add(info);
//	panel3.add(scroller, BorderLayout.SOUTH);
  	info.setVisible(true);
//  	dialog.getContentPane().add(panel3, BorderLayout.SOUTH);
  	panelx.add(panel3, BorderLayout.SOUTH);

        dialog.getContentPane().add(panelx, BorderLayout.NORTH);
        dialog.getContentPane().add(scroller, BorderLayout.CENTER);

    }

/** Implement the run method for Runabout interface.
 */

    public void run() {
	buildGUI();
	dialog.pack();
	fileChooser.setCurrentDirectory(new File(currentdir));
	dialog.setVisible(true);
	if (parentDriver != null) parentDriver.setVisible(false);
    }

/** Reenter from the main toolkit driver. Reset the dialog to visible.
 */

    public void reEnter() {
	dialog.setVisible(true);
	if (parentDriver != null) parentDriver.setVisible(false);
        info.setText("");
	cdf.setText("");
	sklt.setText("");
	cachesizes.setText("");
	variables.setText("");
    }

/** Action for buttons or menu items selection
 */
    public void actionPerformed(ActionEvent evt) {
	Object obj = evt.getSource();
	info.setText("");
	if (obj == quitb || obj == menuFileExit) { // for "Quit" or "Exit"
	     if (macLib == 1) new File(libcdfPath).delete();
             if (frommain == 0) {
		if (modal) dialog.dispose();
		else dialog.setVisible(false);
		if (parentDriver != null) parentDriver.setVisible(true);
             } else {
		System.exit(1);
	     }
	} else if (obj == slt1 || obj == slt2) { // for "Select 1|2" button
             if (obj == slt1) { // for "Select1" button
		doFileChooser("Select/enter a cdf", cdf, 1, filter1);
	     } else { // for "Select2" button
		doFileChooser("Select/enter a skeleton table", sklt, 2, filter2);
             }
	} else if (obj == helpb || obj == menuHelpHelp) { // for "Help" 
		commandX = command + "-java";
		hlp = 1;
		iba = 0;
                String OS = System.getProperty("os.name").toLowerCase();
                if (OS.indexOf("windows") != -1) {
                    cmds[0] = commandX;
                } else if (OS.indexOf("vms") != -1) {
                    cmds[0] = commandX;
                } else {
                    cmds[0] = "/bin/sh";
                    cmds[1] = "-c";
                    cmds[2] = commandX;
                }
                runit(cmds);
                // runit(commandX);
		hlp = 0;
	} else if (obj == entrb) { // for "Enter" button
		iba = 1;
                cdfspec = cdf.getText();
                skltspec = sklt.getText();
		if (cdfspec.equals("") || cdfspec.trim().equals("")) {
                  info.setText("");
                  info.append("Please enter a CDF file...");
                  Toolkit.getDefaultToolkit().beep();
                  return;
		}
		vars = variables.getText();
                if (strva.equals("???") && vars.equals("")) {
                        info.setText("As \"Selected Values\" is " +
                                    "selected, a comma-separated list\n" +
                                    "of delimited variable names like \"var1\" or " +
                                    "\"var1\",\"var2\"is needed in \"Variables\" text field.\n" +
				    "Please enter it now...");
			Toolkit.getDefaultToolkit().beep();
                        variables.requestFocus();
		} else {
			if (strva.equals("")) Values = " ";
			else if (!strva.equals("???")) Values = "-values " + strva + " ";
			     else Values = "-values " + vars + " ";
			temp = strri + strrw + strre;
			if (temp.length() == 0) report = " ";
			else if (temp.length() == 3) report = "-report \"i,w,e\" ";
			else if (temp.length() == 1) {
			   if (strri.length() == 1) report = "-report \"i\" ";
			   if (strrw.length() == 1) report = "-report \"w\" ";
			   if (strre.length() == 1) report = "-report \"e\" ";
			} else {
			   if (strri.length() == 0) report = "-report \"w,e\" ";
			   if (strrw.length() == 0) report = "-report \"i,e\" ";
			   if (strre.length() == 0) report = "-report \"i,w\" ";
			}

			if (stros.equals("")) stros = "-noscreen ";

                        if (strzm.equals("")) Zmode = " ";
                        else Zmode = "-zmode " + strzm + " ";

                        if (strsty.equals("")) estyle = " ";
                        else estyle = "-style " + strsty + " ";

                        if (strnfm.equals("")) enewformat = " ";
                        else enewformat = "-advformat " + strnfm + " ";

			if (skltspec.equals("") || skltspec.trim().equals("")) 
			  SKLTfile = " ";
			else {
			  if (skltspec.startsWith("'")) sktDelimiter = " ";
                  	  else if (skltspec.startsWith("\"")) sktDelimiter = " ";
                  	  else sktDelimiter = "\"";
                          SKLTfile = "-skeleton " + sktDelimiter + skltspec + 
				     sktDelimiter + " ";
                          /*********
                  	  SKLTfile = "-skeleton " + " " + skltspec + " ";
                          *********/
			}

	                caches = cachesizes.getText();
         	        if (caches.equals("") || caches.trim().equals("")) Caches = " ";
    	                else if (caches.startsWith("\"") || caches.startsWith("\'"))
                             Caches = "-cache " + caches.substring(1,caches.length()-2) + " ";
               	        else Caches = "-cache " + caches + " ";

                        if (cdfspec.startsWith("'")) cdfDelimiter = " ";
                        else if (cdfspec.startsWith("\"")) cdfDelimiter = " ";
                        else cdfDelimiter = "\"";

                        commandX = command  + strzz + struf + stros + strlp +
				   strds + strpo + report + estyle +
                                   enewformat + Zmode +
                                   Values + Caches + SKLTfile + cdfDelimiter +
                                   cdfspec + cdfDelimiter;
                        /**************
			commandX = command  + strzz + struf + stros + strlp +
				   strds + strpo + report + estyle + 
                                   enewformat + Zmode +
                                   Values + Caches + SKLTfile + " " + cdfspec + " ";
                        *************/
                        String OS = System.getProperty("os.name").toLowerCase();
                        if (OS.indexOf("windows") != -1) {
                            cmds[0] = commandX;
                        } else if (OS.indexOf("vms") != -1) {
                            commandX = commandX.replace('-', '/');
                            cmds[0] = commandX;
                        } else {
                            cmds[0] = "/bin/sh";
                            cmds[1] = "-c";
                            cmds[2] = commandX;
                        }
                	runit(cmds);
                	// runit(commandX);
		} 
	} else if (obj == cdf) { // "CDF" text field
		cdfspec = cdf.getText();
	} else if (obj == sklt) { // "Skeleton" text field
                skltspec = sklt.getText();
	} else if (obj == cachesizes) { // "CacheSizes" text field
		caches = cachesizes.getText();
	} else if (obj == variables) { // "Variables" text field
                vars = variables.getText();
		values.setSelected((ButtonModel)values4, true);
	} else if (obj == menuEditCopy) {
                if (istart == -1) {
		    info.setText("Where to copy from?");
                    Toolkit.getDefaultToolkit().beep();
                } else {
                    focused.setSelectionStart(istart);
                    focused.setSelectionEnd(iend);
                    focused.copy();
                }
        } else if (obj == menuEditCut) {
                if (istart == -1) {
		    info.setText("What to cut?");
                    Toolkit.getDefaultToolkit().beep();
                } else {
                    focused.setSelectionStart(istart);
                    focused.setSelectionEnd(iend);
                    focused.cut();
                }
        } else if (obj == menuEditPaste) {
                if (focused == null) {
		    info.setText("Where to paste to?");
                    Toolkit.getDefaultToolkit().beep();
                } else {
                  if (istart != -1) {
                    focused.setSelectionStart(istart);
                    focused.setSelectionEnd(iend);
                  }
		  String tempN;
		  try {
		    tempN = (String) Toolkit.getDefaultToolkit().
				    getSystemClipboard().getContents(this).
				    getTransferData(DataFlavor.stringFlavor);
		    if (tempN == null) { // no clipboard text
			info.setText("No current selection on clipboard"); 
			Toolkit.getDefaultToolkit().beep();
		    } else if (tempN.indexOf("\n") != -1) { // multiple lines
			info.setText("Multiple lines selection on clipboard - not allowed:");
			info.append("\n\n");
			info.append(tempN);
			Toolkit.getDefaultToolkit().beep();
		    } else { focused.paste();}
		  } catch (Exception e) {}
                }
        }
    }

/** Action for radio buttons for zMode
 */

    class ZModeListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           strzm = e.getActionCommand();
        }
    }

/** Action for radio buttons for Style
 */

    class StyleListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           strsty = e.getActionCommand();
        }
    }

/** Action for radio buttons for Style
 */

    class AdvFormatListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           strnfm = e.getActionCommand();
           ufc.setSelected(false);
        }
    }

/** Action for radio buttons for Values
 */

    class ValuesListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           strva = e.getActionCommand();
           info.setText("");
           if (strva.equals("???")) { // for "Selected Variables"
             if (variables.getText().equals("")) {
               info.append("Be sure to enter a comma-separated list " +
                           "of the selected variables,\n" +
			   "e.g., \"var1\" or \"var1\",\"var2\",... " +
                           "in the Variables text field\n");
               Toolkit.getDefaultToolkit().beep();
             }
           }
        }

    }

/** Action for checkboxs and combo boxs selection
 */

    public void itemStateChanged(ItemEvent evt) {
	Object obj = evt.getSource();
	if (obj == pgc) { // "Page Output" checkbox
		if (pgc.isSelected()) {
		  info.setText("Page output is not allowed in Java");
		  pgc.setSelected(false);
		  Toolkit.getDefaultToolkit().beep();
	 	}
	} else if (obj == abc) { // "About" checkbox
                if (abc.isSelected()) {
		  abcX = 1;
		  iba = 0;
		  commandX = command + " -about";
                  String OS = System.getProperty("os.name").toLowerCase();
                  if (OS.indexOf("windows") != -1) {
                      cmds[0] = commandX;
                  } else if (OS.indexOf("vms") != -1) {
                      cmds[0] = commandX;
                  } else {
                      cmds[0] = "/bin/sh";
                      cmds[1] = "-c";
                      cmds[2] = commandX;
                  }
                  runit(cmds);
                  // runit(commandX);
                  abc.setSelected(false);
		  abcX = 0;
		}
	} else if (obj == ric) { // "Report Info's" checkbox
                if (ric.isSelected()) {
		  strri = "i";
		  ricX = 1;
	        } else {
		  strri = "";
		  ricX = 0;
		}
        } else if (obj == rwc) { // "Report Warnings" checkbox 
                if (rwc.isSelected()) {
                  strrw = "w";
		  rwcX = 1;
                } else {
                  strrw = "";
		  rwcX = 0;
		}
        } else if (obj == rec) { // "Report Errors" checkbox
                if (rec.isSelected()) {
                  strre = "e";
		  recX = 1;
                } else {
                  strre = "";
		  recX = 0;
		}
        } else if (obj == ufc) { // "Use Format" checkbox
                if (ufc.isSelected()) {
                  struf = "-format ";
                  newformat.clearSelection();
                } else
                  struf = "-noformat ";
        } else if (obj == osc) { // "Output to Screen" checkbox
                if (osc.isSelected()) {
		  bac.setSelected(false);
		  iba = 0;
		  info.setText("Please note: the program may be hung if the ");
		  info.append("output is too big...");
		  Toolkit.getDefaultToolkit().beep();
                  stros = "-screen ";
		  oscX = 1;
                } else {
		  if (oscX == 1) info.setText("");
                  stros = "-noscreen ";
		  oscX = 0;
		}
        } else if (obj == lpc) { // "Log Progress" checkbox
                if (lpc.isSelected()) {
                  strlp = "-log ";
		  lpcX = 1;
                } else {
                  strlp = "-nolog ";
		  lpcX = 0;
		}
	} else if (obj == zzc) { // "-0.0 to 0.0" checkbox
                if (zzc.isSelected())
                  strzz = "-neg2posfp0 ";
                else
                  strzz = "-noneg2posfp0 ";
	} else if (obj == dsc) { // "Display Statistics" checkbox
                if (dsc.isSelected()) {
                  strds = "-statistics ";
		  dscX = 1;
                } else {
                  strds = "-nostatistics ";
		  dscX = 0;
		}
	} else if (obj == bac) { // "Run it Batch" checkbox
                if (bac.isSelected()) {
                  iba = 1;
		  osc.setSelected(false);
		  stros = "-noscreen ";
                  if (cdf.getText().equals("")) {
                     info.setText("");
                     info.append("Please enter a CDF for a batch run...");
                     Toolkit.getDefaultToolkit().beep();
                  }
                } else
                  iba = 0;
        }
    }

    public void focusGained(FocusEvent e) {
        focused = (JTextField)e.getSource();
        if (prevfocused != null) {
            prevfocused.setText(prevfocused.getText());
            if (iend != -1)
                if (iend < focused.getText().length())
                             prevfocused.setCaretPosition(iend);
                else focused.setCaretPosition(focused.getText().length());
        }
    }

    public void focusLost(FocusEvent e) {
        if (istart != -1)     {
            focused.setSelectionStart(istart);
            focused.setSelectionEnd(iend);
            prevfocused = focused;
          }
        }
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {
        if (focused != null) {
          String selectedText = focused.getSelectedText();
          if (selectedText!=null) {
            istart = focused.getSelectionStart();
            iend = focused.getSelectionEnd();
          } else {
            istart = -1;
            iend = -1;
          }
        }
    }

/** Set up gridbaglayout.
 */

    private void makeJButton(Container cont, Object arg,
            int x, int y, int w, int h, double weightx, double weighty) {
        GridBagLayout gbl = (GridBagLayout)cont.getLayout();
        GridBagConstraints c = new GridBagConstraints();
        Component comp;

        c.fill = GridBagConstraints.BOTH;
        c.gridx = x;
        c.gridy = y;
        c.gridwidth = w;
        c.gridheight = h;
        c.weightx = weightx;
        c.weighty = weighty;
        if (arg instanceof String) {
            comp = new JButton((String)arg);
        } else {
            comp = (Component)arg;
        }
        cont.add(comp);
        gbl.setConstraints(comp, c);
    }

/** Execute a command as a separate process for the user selection and returns
    the results in the text area.
 */

    private void runit(String[] command) {
    // private void runit(String command) {
	try {
           String osName = System.getProperty("os.name");
           String cwd = System.getProperty("user.dir");
           libcdfPath = cwd + "/libcdf.dylib";
           if (osName.toLowerCase().indexOf("mac") != -1) {
               File libcdf = new File(libcdfPath);
               if (libcdf.exists()) {
                   macLib = 0;
               } else {
                 if (Files.isWritable(Paths.get(cwd))) {
                   try {
                     cdfbase = System.getProperty("CDF_BASE");
                     if (cdfbase == null)
                         cdfbase = CDFToolsUtil.getenv("CDF_BASE");
                     Files.copy(Paths.get(cdfbase+"/lib/libcdf.dylib"),
                                Paths.get(libcdfPath),
                                StandardCopyOption.REPLACE_EXISTING);
                     macLib = 1;
                   } catch (Exception ex) {
                     System.out.println ("**** Error for copying... "+ex);
                   }
                 }
               }
           }

           if (command[1] != null)
                  process = runtime.exec(command);
           else
                  process = runtime.exec(command[0]);
/*
                if (iba == 1 && hlp == 0 && abcX == 0) {
                        info.setText("Program is submitted...\n\n");
                        String myString;
                        if (sklt.getText().equals("") || sklt.getText().trim().equals("")) {
                          myString = cdf.getText().trim();
                          int id;
                          id = myString.lastIndexOf('/');
                          if (id > 0) myString = myString.substring(id+1);
                          myString = myString + ".skt";
			} else myString = sklt.getText().trim() + ".skt";
                        info.append("A skeleton table: "+myString+"  will/may be created.\n");
                } else {
                  if (abcX == 0 && hlp == 0) {
                          info.setText("Program is running...\n");
                  }
*/
	   Dimension dialogSize = dialog.getSize();
	   ((JComponent)(dialog.getContentPane())).paintImmediately(
  						0, 0, dialogSize.width, dialogSize.height);
	   String line = null;
	   boolean first = true;
           InputStreamReader inReader2 = new InputStreamReader(process.getInputStream(), "UTF-8");
           BufferedReader inStream = new BufferedReader(inReader2, 8192);

	   if (hlp == 1 || abcX == 1 || ricX == 1 || rwcX == 1 || recX == 1 ||
	       lpcX == 1 || dscX == 1 || oscX == 1) {
               while ((line = inStream.readLine()) != null) {
		   if (first) {
			info.setText("");
			first = false;
		   }
                   info.append(line+"\n");
	       }
	   }
           process.waitFor();
	   info.setCaretPosition(0);
	   if (process.exitValue() == 1) 
		    Toolkit.getDefaultToolkit().beep();
           else {
		if (iba == 1) {
		   if (info.getText().toLowerCase().indexOf("error") == -1)
			info.append("Done!\n\n");
		   else 
			info.append("ERROR: skeleton table is invalid.\n");
		}
	   } 
	} catch (Exception e) {
                info.setText("error executing: "+e);
                Toolkit.getDefaultToolkit().beep();
	}

    }

/** Initiate the file chooser and strip the extension for the selected file
    if necessary
 */

    private void doFileChooser (String title, JTextField textField, int theone, SimpleFileFilter filter) {
//       	JFileChooser fileChooser = new JFileChooser();
	ExampleFileView fileView = new ExampleFileView();
//       	fileChooser.setCurrentDirectory(new File(currentdir));
       	fileChooser.setDialogTitle(title);
       	fileChooser.addChoosableFileFilter(filter1);
	fileChooser.addChoosableFileFilter(filter2);
        if (filter != null) fileChooser.setFileFilter(filter);
        try {
           fileView.putIcon("cdf",
                            new ImageIcon(SkeletonTable.class.getResource("CDF_Logo3.gif")));
           fileView.putIcon("CDF",
                            new ImageIcon(SkeletonTable.class.getResource("CDF_Logo3.gif")));
           fileChooser.setFileView(fileView);
        } catch (Exception e) {}

        int returnValue = fileChooser.showDialog(dialog, "OK");
        if (returnValue == JFileChooser.APPROVE_OPTION) {
           File selectedFile = fileChooser.getSelectedFile();
           if (selectedFile != null) {
              int ind;
              String myfile = selectedFile.getAbsolutePath();
	      if (theone == 1) { // for .cdf file
                  ind = myfile.lastIndexOf(".cdf");
                  if (ind != -1) myfile = myfile.substring(0, ind);
                  ind = myfile.lastIndexOf(".CDF");
                  if (ind != -1) myfile = myfile.substring(0, ind);
	      } else { // for .skt file
                  ind = myfile.lastIndexOf(".skt");
                  if (ind != -1) myfile = myfile.substring(0, ind);
                  ind = myfile.lastIndexOf(".SKT");
                  if (ind != -1) myfile = myfile.substring(0, ind);
	      }
	      fileChooser.setCurrentDirectory(selectedFile);
              textField.setText(myfile);
           }
        } else {
//         JOptionPane.showMessageDialog(dialog, "No file chosen");
        }
    }

/** This class can run as an application by its own.
 */

    static public void main(String[] args) {

        String cdfbase = System.getProperty("CDF_BASE");
        if (cdfbase == null) 
            cdfbase = CDFToolsUtil.getenv("CDF_BASE");

        SkeletonTable thispgm = new SkeletonTable(null, cdfbase);
	thispgm.fileChooser.setCurrentDirectory(new File(thispgm.currentdir));
        thispgm.frommain = 1;
	thispgm.run();
    }

}

