/**
 * *************************************************************************
 * Copyright (C) 2009 by Paul Lutus * lutusp@arachnoid.com * * This program is
 * free software; you can redistribute it and/or modify * it under the terms of
 * the GNU General Public License as published by * the Free Software
 * Foundation; either version 2 of the License, or * (at your option) any later
 * version. * * This program is distributed in the hope that it will be useful,
 * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General
 * Public License for more details. * * You should have received a copy of the
 * GNU General Public License * along with this program; if not, write to the *
 * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA. *
 * *************************************************************************
 */
/*
 * TankVolume.java
 *
 * Created on Feb 9, 2009, 1:22:15 AM
 */
package tankcalc;

import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.parser.*;

/**
 *
 * @author lutusp
 */
final public class TankCalc extends javax.swing.JPanel implements ClipboardOwner {

    public String programName;
    public String VERSION = "7.4";
    JFrame appFrame;
    InitManager initManager = null;
    protected Rectangle screenBounds;  // default size
    boolean applet = false;
    ArrayList<Double[]> dblList = null;
    ArrayList<ArrayList<String>> strTableArray = null;
    ArrayList<String> strHeaderArray = null;
    int[] intColumnWidths;
    HelpPane helpPane = null;
    protected int helpScrollPos = 0;
    SurfaceAreaMassComputer samc = null;
    TankProcessor tankProcessor;
    TankProperties sharedTP;

    boolean enabled = false;
    boolean makeTableFlag;
    String tableTitle[];
    int helpSlideIndex = 0;
    NumberFormat numberFormat;
    String[] helpSlides = {
        "tank_dimensional_diagram_half.png",
        "tank_end_cap_description_half.png",
        "tank_math_description_half.png",
        "tank_sensor_placement_half.png"
    };

    TankImageView mainPanel3d = null;
    TankImageView subPanel3d = null;
    Color graphicBackgroundColor;
    Color graphicForegroundColor;
    double graphicCurrentFactor;
    CopyPasteTankDescription copyPasteDescription;
    ImageGenerator imageGenHi, imageGenLo;
    int mostRecentTableType = -1;
    boolean inverseMode = false;

    /**
     * Creates new form TankVolume
     */
    public TankCalc(JFrame p, boolean appl, String[] args) {
        appFrame = p;
        final String[] progArgs = args;
        resetConfig(appFrame);
        initManager = new InitManager(this, applet);
        tankProcessor = new TankProcessor();
        imageGenHi = new ImageGenerator(tankProcessor, sharedTP, false);
        imageGenLo = new ImageGenerator(tankProcessor, sharedTP, true);

        this.applet = appl;
        programName = getClass().getSimpleName();
        // this is essential to avoid a problem with
        // HTMLEditorKit and applets
        ParserDelegator workaround = new ParserDelegator();
        // just for testing locale issues
        // Locale.setDefault(Locale.GERMANY);
        numberFormat = NumberFormat.getInstance();
        initComponents();

        //tableScrollPane.getViewport().setBackground(Color.white);
        // Just for the first run
        int w = 800;
        int h = 650;
        Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
        screenBounds = new Rectangle((ss.width - w) / 2, (ss.height - h) / 2, w, h);

        ArrayList<JComboBox<Integer>> boxes = new ArrayList<JComboBox<Integer>>();

        boxes.add(xLinesComboBox);

        boxes.add(yLinesComboBox);

        loadNumberBoxes(boxes, 0, 512, 16);

        boxes.clear();
        boxes.add(lineThicknessComboBox);
        boxes.add(transparencyComboBox);

        loadNumberBoxes(boxes, 0, 10, 1);

        samc = new SurfaceAreaMassComputer(this, sharedTP);
        copyPasteDescription = new CopyPasteTankDescription(this);

        helpPane = new HelpPane(this);

        GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        helpPanel.add(helpPane, gridBagConstraints);

        mainPanel3d = new TankImageView(this, sharedTP);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        graphicDisplayPanel.add(mainPanel3d, gridBagConstraints);

        mainPanel3d.setPaintChipColors();

        subPanel3d = new TankImageView(this, sharedTP);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        viewPanel.add(subPanel3d, gridBagConstraints);

        //horizontalMode = !verticalMode;
        //horizontalRadioButton.setSelected(horizontalMode);
        loadComboBox(inputUnitsComboBox, Constants.inputUnitNames, 3);
        loadComboBox(outputUnitsComboBox, Constants.outputUnitVolumeNames, 6);
        loadDecComboBox();
        if (appFrame != null) {
            appFrame.setBounds(screenBounds);
        }

        //String s = readResourceFile("help_resources/ConfigurationNote.txt");
        //configHelpTextArea.setText(s);
        //configHelpTextArea.select(0, 0);
        manageHelpSlides(0);
        setWheelActions();
        initManager.getDefaultValues();
        if (!applet) {
            initManager.readConfig();
            writeValues();
        }
        mainTabbedPane.setSelectedIndex(sharedTP.currentTab);
        enabled = true;
        processArgs(progArgs);
        setModeAndLabels();
        updateGraphicImages();
        processTabClick();

        SwingUtilities.invokeLater(
                new Runnable() {

                    @Override
                    public void run() {
                        helpPane.setScrollPos(helpScrollPos);
                    }
                });
    }

    void resetConfig(JFrame p) {
        sharedTP = new TankProperties();
        sharedTP.programFrame = p;
    }

    void setConfigurationDefaults() {
        if (userRequest("Okay to reset default values?")) {
            enabled = false;
            resetConfig(appFrame);
            writeValues();
            enabled = true;
            mainPanel3d.updateSettings(sharedTP);
            subPanel3d.updateSettings(sharedTP);
            tankProcessor.setValues(this,sharedTP);
            samc.updateSettings(sharedTP);
            setModeAndLabels();
        }
    }

    void p(String s) {
        System.out.println(s);
    }

    String pn(double n) {
        return String.format("%.4f", n);
    }

    boolean processArgs(String[] args) {
        boolean success = true;
        if (args != null && args.length > 0) {
            success = false;
            for (int i = 0; i < args.length; i++) {
                //(args[i]);
                if (success = copyPasteDescription.pasteTankDescription(args[i])) {
                    break;
                }
            }
            if (!success) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        copyPasteDescription.showError("program arguments");
                    }
                });
            }
        }
        return success;
    }

    void setWheelActions() {
        new UserActionManager(tankAngleTextField, 0, 90, this);
        new UserActionManager(g_LTextField, 0, 100000, this);
        new UserActionManager(g_RTextField, 0, 10000, this);
        new UserActionManager(sensorXTextField, -1000000, 1000000, this);
        new UserActionManager(sensorYTextField, -1000000, 1000000, this);
        new UserActionManager(sensorZTextField, -1000000, 1000000, this);
        new UserActionManager(residVolumeTextField, -1000000, 1000000, this);
        new UserActionManager(g_rLTextField, 0, 1000000, this);
        new UserActionManager(g_rRTextField, 0, 1000000, this);
        new UserActionManager(lineThicknessComboBox, 0, 32, this);
        new UserActionManager(yLinesComboBox, 0, 512, this);
        new UserActionManager(xLinesComboBox, 0, 512, this);
        new UserActionManager(transparencyComboBox, 0, 10, this);
    }

    void loadNumberBoxes(ArrayList<JComboBox<Integer>> boxes, int a, int b, int def) {
        for (JComboBox<Integer> box : boxes) {
            box.removeAllItems();
            for (int x = a; x <= b; x++) {
                box.addItem(x);
            }
            box.setSelectedIndex(def);
        }

    }

    void loadComboBox(JComboBox<String> box, String[] list, int def) {
        box.removeAllItems();
        for (String s : list) {
            box.addItem("<html>" + s + "</html>");
        }
        box.setSelectedIndex(def);
    }

    void loadDecComboBox() {
        decimalPlacesComboBox.removeAllItems();
        for (int i = 0; i <= 16; i++) {
            decimalPlacesComboBox.addItem(i);
        }
        decimalPlacesComboBox.setSelectedIndex(sharedTP.defaultDecimalPlaces);
    }

    // this responds to a custom parameter
    // from the applet environment
    public void setVerticalMode(boolean mode) {
        if (mode) {
            this.tankOrientationComboBox.setSelectedItem("Vertical");
            getHVTMode();
        }
    }

    void getHVTMode() {
        sharedTP.tankOrientation = tankOrientationComboBox.getSelectedIndex();
        sharedTP.sensorOrientation = sensorOrientationComboBox.getSelectedIndex();
    }

    void getInverseMode() {
        //sharedTP.inverseMode = inverseRadioButton.isSelected();
    }

    void getInputUnits() {
        sharedTP.inputUnitIndex = inputUnitsComboBox.getSelectedIndex();
    }

    void getOutputUnits() {
        sharedTP.outputUnitIndex = outputUnitsComboBox.getSelectedIndex();
    }

    String getUnitLabel(boolean hvLabel, boolean height, boolean inverse, boolean input, boolean capitalize) {
        String result = "";
        if (hvLabel) {
            result += ((height ^ inverse) ? "Height " : "Volume ");
        }
        result += ((input ^ inverse) ? Constants.inputUnitNames[sharedTP.inputUnitIndex] : Constants.outputUnitVolumeNames[sharedTP.outputUnitIndex]);
        if (!capitalize) {
            result = result.toLowerCase();
        }
        return result;
    }

    //protected double sensorOffset() {
    //    return tankVolumeIntegrator.convertLengthUnits(tankVolumeIntegrator.trueSensorOffset, true);
    // }
    void showMaxValues() {
        readValues();
        double maxh = tankProcessor.convertLengthUnits(tankProcessor.maxHeight, true);
        double maxVolumeConverted = tankProcessor.convertVolumeUnits(tankProcessor.maxVolume, true);
        double sensorOff = tankProcessor.convertLengthUnits(tankProcessor.trueSensorOffset, true);
        String vals = "Tank internal height: " + formatNum(maxh) + " " + sharedTP.currentInputUnitName;
        vals += ", sensor offset " + formatNum(sensorOff) + " " + sharedTP.currentInputUnitName;
        vals += ", volume: " + formatNum(maxVolumeConverted) + " " + sharedTP.currentOutputUnitName;
        String msg = "<html>" + vals + "</html>";
        setStatus(msg, false);
    }

    void setModeAndLabels() {
        if (enabled) {
            boolean success = readValues();
            tankAngleTextField.setEnabled(sharedTP.tankOrientation == Constants.TANKTILTED);
            tankAngleLabel.setEnabled(sharedTP.tankOrientation == Constants.TANKTILTED);
            transparencyComboBox.setEnabled(sharedTP.polygonMode);
            transparencyLabel.setEnabled(sharedTP.polygonMode);
            lineThicknessComboBox.setEnabled(!sharedTP.polygonMode);
            lineThicknessLabel.setEnabled(!sharedTP.polygonMode);
            LVariableLabel.setText(" Cylinder length (L) " + sharedTP.currentInputUnitName);
            RVariableLabel.setText(" Cylinder radius (R) " + sharedTP.currentInputUnitName);
            lbVariableLabel1.setText(" Left/bottom cap radius (r) " + sharedTP.currentInputUnitName);
            rtVariableLabel1.setText(" Right/top cap radius (r) " + sharedTP.currentInputUnitName);
            //right_rVariableLabel.setText("<html><b>r</b> (end cap radius) " + currentInputUnit + "</html>");
            inputLabel.setText("<html> Enter " + getUnitLabel(true, true, inverseMode, true, false) + ":</html>");
            outputLabel.setText("<html> Result " + getUnitLabel(true, false, inverseMode, false, false) + ":</html>");
            heightStepSizeLabel.setText("<html>&nbsp;Height Table Step Size " + getUnitLabel(false, true, false, true, false) + "</html>");
            volumeStepSizeLabel.setText("<html>&nbsp;Volume Table Step Size " + getUnitLabel(false, true, true, true, false) + "</html>");
            residVolumeLabel.setText("<html>&nbsp;Residual " + getUnitLabel(true, false, false, false, false) + "</html>");
            xCoordLabel.setText(" Sensor X position " + getUnitLabel(false, true, false, true, false));
            yCoordLabel.setText(" Sensor Y position " + getUnitLabel(false, true, false, true, false));
            zCoordLabel.setText(" Sensor Z position " + getUnitLabel(false, true, false, true, false));
            wallThicknessLabel.setText(" Wall thickness " + sharedTP.currentInputUnitName);
            mainPanel3d.createTankImage(sharedTP);
            if (success) {
                showMaxValues();
            }
            subPanel3d.repaint();
        }
    }

    void setModeIfEnter(KeyEvent evt) {
        //p("" + evt);
        if (evt.getKeyChar() == '\n') {
            setModeAndLabels();
        }
    }

    void setStatus(String s, boolean error) {
        statusLabel.setText(s);
        if (error) {
            Toolkit.getDefaultToolkit().beep();
        }
    }

    double getDouble(String s) {
        double v = 0;
        double e;
        try {
            // deal with possibility of exponent
            // which numberformat cannot process
            s = s.toLowerCase();
            String[] array = s.split("e");
            v = numberFormat.parse(array[0]).doubleValue();
            if (array.length > 1) {
                // get signed exponent
                e = numberFormat.parse(array[1]).doubleValue();
                v *= Math.pow(10, e);
            }
        } catch (ParseException ex) {
            //System.out.println(getClass().getName() + ".getDouble: Error: " + ex);
        }
        return v;
    }

    /*
     * modes:
     *
     * 0 = default, no special content
     * 1 = allow percent to be slope: convert to atan(v/100);
     * 2 = allow "d" to trigger r = R tan (angle)
     *
     */
    double getDoubleForTextField(JTextField tf, String label, int mode) {
        double v = 0;
        String s = tf.getText();
        // special case of slope % entry
        switch (mode) {
            case 0: // ordinary conversion
                v = getDouble(s);
                break;
            case 1: // tank angle entry, allow % slope
                if (s.matches(".*%.*")) {
                    sharedTP.tankAngleUnitIndex = Constants.ENTRYSLOPE;
                    v = getDouble(s.replaceAll("%", ""));
                } else {
                    sharedTP.tankAngleUnitIndex = Constants.ENTRYDEGREES;
                    v = getDouble(s);
                }
                break;
            case 2:
                // cone entry, allow either
                // nnnd angle entry or nnn% slope
                if (s.matches(".*d.*")) {
                    v = getDouble(s.replaceAll("d", ""));
                    v = Math.tan(v * Constants.radian) * sharedTP.g_R;
                } else if (s.matches(".*%.*")) { // slope entry
                    v = getDouble(s.replaceAll("%", ""));
                    v = (v / 100.0) * sharedTP.g_R;
                } else {
                    v = getDouble(s);  // ordinary height entry
                }
                break;
            default:
                v = getDouble(s);  // ordinary height entry
                break;
        }

        if (Double.isNaN(v)) {
            v = 0;
            tf.setText("0");
        }
        return v;
    }

    int getIntForTextField(JTextField tf, String label) {
        int v = 0;
        try {
            String s = tf.getText();
            v = Integer.parseInt(s);
        } catch (Exception e) {
            setStatus("Error: Bad entry for " + label, true);
        }
        return v;
    }

    int setEndCapMode(JRadioButton[] array) {
        int i;
        for (i = 0; i < array.length; i++) {
            if (array[i].isSelected()) {
                break;
            }
        }
        return i;
    }

    void errorMessage(String s) {
        beep();
        JOptionPane.showMessageDialog(this, s, programName + " " + VERSION + " Error", JOptionPane.WARNING_MESSAGE);
    }

    boolean userRequest(String s) {
        Object[] options = {"No", "Yes"};
        beep();
        int r = JOptionPane.showOptionDialog(this,
                s,
                programName + " " + VERSION,
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE,
                null,
                options,
                options[0]);
        return r == 1;
    }

    boolean readValues() {
        boolean result = true;
        if (enabled) {
            sharedTP.decimalPlaces = decimalPlacesComboBox.getSelectedIndex();
            sharedTP.wallThickness = getDoubleForTextField(wallThicknessTextField, " wall thickness", 0);
            sharedTP.wallDensity = getDoubleForTextField(wallDensityTextField, " wall density", 0);
            sharedTP.contentDensity = getDoubleForTextField(contentDensityTextField, " content density", 0);
            sharedTP.weightUnitIndex = weightUnitsComboBox.getSelectedIndex();
            sharedTP.weightUnitName = (String) weightUnitsComboBox.getSelectedItem();
            sharedTP.inputUnitIndex = inputUnitsComboBox.getSelectedIndex();
            sharedTP.outputUnitIndex = outputUnitsComboBox.getSelectedIndex();
            //sharedTP.inverseMode = inverseRadioButton.isSelected();
            sharedTP.residualVolume = getDoubleForTextField(residVolumeTextField, " residual volume value", 0);
            sharedTP.rootFinderEpsilon = getDoubleForTextField(rootFinderEpsilonTextField, " root finder epsilon value", 0);
            sharedTP.cylinderIntegrationSteps = getIntForTextField(cylinderIntegrationStepsTextField, " cylinder integration steps value");
            sharedTP.endCapIntegrationSteps = getIntForTextField(endCapIntegrationStepsTextField, " end cap integration steps value");
            sharedTP.leftEndCapMode = leftCapComboBox.getSelectedIndex();
            sharedTP.rightEndCapMode = rightCapComboBox.getSelectedIndex();
            sharedTP.tankOrientation = tankOrientationComboBox.getSelectedIndex();
            sharedTP.sensorOrientation = sensorOrientationComboBox.getSelectedIndex();

            sharedTP.enteredAngleDegrees = getDoubleForTextField(tankAngleTextField, "A (tank Angle) value", 1); // allow slope % entry

            sharedTP.g_L = getDoubleForTextField(g_LTextField, "L (cylinder Length) value", 0);

            sharedTP.g_R = getDoubleForTextField(g_RTextField, "R (cylinder radius) value", 0);
            // allow either nnnd degrees or nnn% slope entries
            sharedTP.g_rL = getDoubleForTextField(g_rLTextField, "left r (end cap radius) value", 2);
            // allow either nnnd degrees or nnn% slope entries
            sharedTP.g_rR = getDoubleForTextField(g_rRTextField, "right r (end cap radius) value", 2);
            sharedTP.scalingFactor = getDoubleForTextField(scalingFactorTextField, " scaling factor value", 0);
            sharedTP.sensorPositionX = getDoubleForTextField(sensorXTextField, " sensor X position value", 0);
            sharedTP.sensorPositionY = getDoubleForTextField(sensorYTextField, " sensor Y position value", 0);
            sharedTP.sensorPositionZ = getDoubleForTextField(sensorZTextField, " sensor Z position value", 0);

            sharedTP.graphicDrawLeftCap = leftCapCheckBox.isSelected();
            sharedTP.graphicDrawRightCap = rightCapCheckBox.isSelected();
            sharedTP.graphicDrawCylinder = cylinderCheckBox.isSelected();
            sharedTP.graphicDrawSensor = sensorCheckBox.isSelected();

            sharedTP.graphicAnaglyphMode = anaglyphCheckBox.isSelected();
            sharedTP.graphicInverseMode = inverseCheckBox.isSelected();
            sharedTP.polygonMode = polygonCheckBox.isSelected();
            sharedTP.polygonTransparency = transparencyComboBox.getSelectedIndex();
            sharedTP.graphicAntialiasingMode = antialiasingCheckBox.isSelected();
            sharedTP.graphicLineThickness = lineThicknessComboBox.getSelectedIndex();
            sharedTP.graphicXDrawSteps = xLinesComboBox.getSelectedIndex();
            sharedTP.graphicYDrawSteps = yLinesComboBox.getSelectedIndex();

            sharedTP.currentInputUnitName = getUnitLabel(false, true, false, true, false);
            sharedTP.currentOutputUnitName = getUnitLabel(false, false, false, false, false);

            sharedTP.tableTitle = tableTitleTextField.getText();
            sharedTP.tableHeightStepSize = getDoubleForTextField(tableHeightStepSizeTextField, " height step size", 0);
            sharedTP.tableVolumeStepSize = getDoubleForTextField(tableVolumeStepSizeTextField, " volume step size", 0);

            //if (htmlTableRadioButton.isSelected()) {
            //    sharedTP.tableType = Constants.TABLEHTML;
            //} else if (csvTableRadioButton.isSelected()) {
            //    sharedTP.tableType = Constants.TABLECSV;
            //} else if (plainTableRadioButton.isSelected()) {
            //    sharedTP.tableType = Constants.TABLEPLAIN;
            //}

            if (!sharedTP.tankUpright && Math.abs(sharedTP.sensorPositionZ) > sharedTP.g_R) {
                setStatus("Z value may not exceed tank radius in this mode", true);
                sharedTP.sensorPositionZ = (sharedTP.sensorPositionZ < 0) ? -sharedTP.g_R : sharedTP.g_R;
                sensorZTextField.setText(formatNum(sharedTP.sensorPositionZ));
                result = false;
            } else {

                result = tankProcessor.setValues(this,sharedTP);
                if (!result) {
                    setStatus("One of more entered values exceeds permitted limits", true);
                }
            }
            updateGraphicImages();
        }
        return result;
    }

    String doubleToString(double v) {

        return "" + v;
    }

    String intToString(int v) {
        return String.format("%d", v);
    }

    void setComboBox(JComboBox box, int index) {
        if (index >= 0 && index < box.getItemCount()) {
            box.setSelectedIndex(index);
        }
    }

    protected void writeValues() {
        setComboBox(decimalPlacesComboBox, sharedTP.decimalPlaces);
        wallThicknessTextField.setText(doubleToString(sharedTP.wallThickness));
        wallDensityTextField.setText(doubleToString(sharedTP.wallDensity));
        contentDensityTextField.setText(doubleToString(sharedTP.contentDensity));
        contentDensityTextField.setText(doubleToString(sharedTP.contentDensity));
        setComboBox(weightUnitsComboBox, sharedTP.weightUnitIndex);
        setComboBox(inputUnitsComboBox, sharedTP.inputUnitIndex);
        setComboBox(outputUnitsComboBox, sharedTP.outputUnitIndex);
        //inverseRadioButton.setSelected(sharedTP.inverseMode);
        residVolumeTextField.setText(doubleToString(sharedTP.residualVolume));
        rootFinderEpsilonTextField.setText(doubleToString(sharedTP.rootFinderEpsilon));
        cylinderIntegrationStepsTextField.setText(intToString(sharedTP.cylinderIntegrationSteps));
        endCapIntegrationStepsTextField.setText(intToString(sharedTP.endCapIntegrationSteps));
        setComboBox(leftCapComboBox, sharedTP.leftEndCapMode);
        setComboBox(rightCapComboBox, sharedTP.rightEndCapMode);
        setComboBox(tankOrientationComboBox, sharedTP.tankOrientation);
        setComboBox(sensorOrientationComboBox, sharedTP.sensorOrientation);
        tankAngleTextField.setText(doubleToString(sharedTP.enteredAngleDegrees));
        g_LTextField.setText(doubleToString(sharedTP.g_L));
        g_RTextField.setText(doubleToString(sharedTP.g_R));
        g_rLTextField.setText(doubleToString(sharedTP.g_rL));
        g_rRTextField.setText(doubleToString(sharedTP.g_rR));
        scalingFactorTextField.setText(doubleToString(sharedTP.scalingFactor));

        sensorXTextField.setText(doubleToString(sharedTP.sensorPositionX));
        sensorYTextField.setText(doubleToString(sharedTP.sensorPositionY));
        sensorZTextField.setText(doubleToString(sharedTP.sensorPositionZ));

        anaglyphCheckBox.setSelected(sharedTP.graphicAnaglyphMode);
        inverseCheckBox.setSelected(sharedTP.graphicInverseMode);
        polygonCheckBox.setSelected(sharedTP.polygonMode);
        antialiasingCheckBox.setSelected(sharedTP.graphicAntialiasingMode);
        leftCapCheckBox.setSelected(sharedTP.graphicDrawLeftCap);
        rightCapCheckBox.setSelected(sharedTP.graphicDrawRightCap);
        cylinderCheckBox.setSelected(sharedTP.graphicDrawCylinder);
        sensorCheckBox.setSelected(sharedTP.graphicDrawSensor);

        setComboBox(transparencyComboBox, sharedTP.polygonTransparency);
        setComboBox(lineThicknessComboBox, sharedTP.graphicLineThickness);
        setComboBox(xLinesComboBox, sharedTP.graphicXDrawSteps);
        setComboBox(yLinesComboBox, sharedTP.graphicYDrawSteps);

        tableTitleTextField.setText(sharedTP.tableTitle);

        tableHeightStepSizeTextField.setText(doubleToString(sharedTP.tableHeightStepSize));
        tableVolumeStepSizeTextField.setText(doubleToString(sharedTP.tableVolumeStepSize));

        //htmlTableRadioButton.setSelected(sharedTP.tableType == Constants.TABLEHTML);
        //csvTableRadioButton.setSelected(sharedTP.tableType == Constants.TABLECSV);
        //plainTableRadioButton.setSelected(sharedTP.tableType == Constants.TABLEPLAIN);

    }

    void detectEnterKey(KeyEvent evt) {
        if (evt.getKeyChar() == '\n') {
            computeSingleResult();
        }
    }

    String formatNum(double v) {
        if (Double.isNaN(v)) {
            return " -- ";
        }
        String s = String.format("%." + sharedTP.decimalPlaces + "f", v);
        return s;
    }

    void computeSingleResult() {
        double y, v, max;
        setModeAndLabels();
        if (readValues()) {
            y = getDoubleForTextField(singleInputField, "input", 0);
            if (Double.isNaN(y)) {
                setStatus("Error: input argument out of range", true);
                singleOutputField.setText("");
            } else {
                if (inverseMode) {
                    y = tankProcessor.convertVolumeUnits(y, false);
                    max = tankProcessor.computeMaxVolume().volume;
                    if (y <= max) {
                        v = tankProcessor.heightForVolume(y).height;
                        v = tankProcessor.convertLengthUnits(v, true);
                    } else {
                        setStatus("Error: input argument exceeds maximum volume", true);
                        singleOutputField.setText("");
                        return;
                    }
                } else { // normal mode
                    y = tankProcessor.convertLengthUnits(y, false);
                    //max = computeMaxHeight();
                    //if (y <= max) {
                    v = tankProcessor.volumeForHeight(y).volume;
                    v = tankProcessor.convertVolumeUnits(v, true);
                    //} else {
                    //    setStatus("Error: input argument exceeds maximum height", true);
                    //    singleOutputField.setText("");
                    //    return;
                    //}
                }
                String result = formatNum(v);
                singleOutputField.setText(result);
            }
        }
    }

    protected String plainTextConvertExponents(String s) {
        return s.replaceAll("&sup(\\d);", "^$1");
    }

    ArrayList<String> computeLine(ArrayList<Double[]> array, double y, double max) {
        double x;
        TankCompResult z = tankProcessor.computeHeightOrVolume(y);
        if (Double.isNaN(z.volume)) {
            if (!inverseMode) {
                z = tankProcessor.tankFullVolume();
                z.volume *= sharedTP.scalingFactor;
            } else {
                z.volume = tankProcessor.maxHeight;
            }
        }
        if (inverseMode) {
            x = tankProcessor.convertLengthUnits(z.height, true);
            y = tankProcessor.convertVolumeUnits(y, true);
        } else {
            x = tankProcessor.convertVolumeUnits(z.volume, true);
            y = tankProcessor.convertLengthUnits(y, true);
        }
        z.wettedArea = tankProcessor.convertAreaUnits(z.wettedArea, true);
        z.surfaceArea = tankProcessor.convertAreaUnits(z.surfaceArea, true);
        if (array != null) {
            array.add(new Double[]{y, z.volume, z.wettedArea, z.surfaceArea});
        }
        String a = formatNum(y);
        String b = formatNum(x);
        String c = formatNum(z.wettedArea);
        String d = formatNum(z.surfaceArea);
        String pct = formatNum(z.volume * 100.0 / max);
        return new ArrayList<String>(Arrays.asList(a, b, c, d, pct));
    }

    void addTableRecord(ArrayList<String> record, boolean header) {
        for (int i = 0; i < record.size(); i++) {
            intColumnWidths[i] = Math.max(intColumnWidths[i], record.get(i).length() + 2);
        }
        if (header) {
            strHeaderArray = record;
        } else {
            strTableArray.add(record);
        }
    }

    boolean stringArraysMatch(ArrayList<String> a, ArrayList<String> b) {
        if (a != null && b != null && a.size() > 0 && a.size() == b.size()) {
            int i = 0;
            for (String s : a) {
                if (!s.equals(b.get(i))) {
                    return false;
                }
                i++;
            }
            return true;
        } else {
            return false;
        }
    }

    void buildDataTable() {
        if (!Double.isNaN(sharedTP.tableHeightStepSize) && !Double.isNaN(sharedTP.tableVolumeStepSize)) {
            double max, y;
            //StringBuilder sb = new StringBuilder();
            // create table title strings
            String u1 = getUnitLabel(false, true, false, true, true);
            String u2 = Constants.outputUnitAreaNames[sharedTP.inputUnitIndex];
            String u3 = getUnitLabel(false, false, false, false, true);
            String a, b;

            if (inverseMode) {
                b = "Sensor Height " + u1;
                a = "LV " + u3;

            } else {
                a = "Sensor Height " + u1;
                b = "LV " + u3;
            }
            String c = "LWA " + u2;
            String d = "LSA " + u2;
            String e = "%";
            double step = 0;
            if (inverseMode) {
                step = tankProcessor.convertVolumeUnits(sharedTP.tableVolumeStepSize, false);
                max = tankProcessor.computeMaxVolume().volume * sharedTP.scalingFactor;
            } else {
                step = tankProcessor.convertLengthUnits(sharedTP.tableHeightStepSize, false);
                max = tankProcessor.computeFullTankHeight();
                max /= tankProcessor.sensorScalingFactor();
            }
            if (Double.isNaN(max) || Math.abs(max) > 1e10) {
                beep();
                JOptionPane.showMessageDialog(this, "Sensor path anomaly -- cannot create table", "Table Generation Error", JOptionPane.INFORMATION_MESSAGE);
            } else {
                addTableRecord(new ArrayList<>(Arrays.asList(a, b, c, d, e)), true);
                // generate table data rows
                int n;
                computeLine(dblList, max, max);
                double maxVal = dblList.get(0)[1];
                dblList.clear();
                ArrayList<String> array = new ArrayList<>();
                for (int iy = 0; ((y = iy * step) <= max) && makeTableFlag; iy++) {
                    array = computeLine(dblList, y, maxVal);
                    addTableRecord(array, false);
                    n = (int) ((y / max) * 100.0);
                    tableProgressBar.setString("Building Table (" + n + "%)");
                    tableProgressBar.setValue(n);
                    //p("y = " + y + ", max = " + max);
                }
                ArrayList<String> lastLine = array;
                array = computeLine(dblList, max, maxVal);
                strTableArray.add(array);
                if (makeTableFlag) {
                    // sometimes the "max" value line is identical to the
                    // prior line, don't include if this is so
                    if (stringArraysMatch(lastLine, array)) {
                        dblList.remove(dblList.size() - 1);
                        strTableArray.remove(strTableArray.size() - 1);
                    }
                }
            }
        }
    }

    void buildSpecTable() {
        samc.createList();
    }

    void buildTableGeneric(int type) {
        mostRecentTableType = type;
        intColumnWidths = new int[]{0, 0, 0, 0, 0};
        setModeAndLabels();
        tableCancelButton.setEnabled(true);
        if (readValues()) {
            dblList = new ArrayList<>();
            strTableArray = new ArrayList<>();
            strHeaderArray = new ArrayList<>();
            //tableTextPane.setText("");
            tableProgressBar.setStringPainted(true);
            if (type == Constants.DATATABLE) {
                buildDataTable();
            } else {
                buildSpecTable();
            }
            //p("done generating table");
            if (makeTableFlag) {
                setStatus("Created table with " + strTableArray.size() + " records", false);
                //p("done formatting table");
            } else {
                dblList = new ArrayList<>(); // erase partial table
                setStatus("Table Build Canceled", true);
            }
        }
        tableProgressBar.setValue(0);
        tableProgressBar.setString("");
        makeTableFlag
                = false;
        tableCancelButton.setEnabled(false);
        updateTableDisplay();
    }

    void buildDataTableThread(final int type) {
        if (!makeTableFlag) {
            makeTableFlag = true;
            Thread t = new Thread() {

                @Override
                public void run() {
                    buildTableGeneric(type);
                }
            };
            t.start();
        } else {
            beep();
        }
    }

    protected void buildTable(int type,boolean inverse) {
        eraseSingleEntry();
        inverseMode = inverse;
        buildDataTableThread(type);
    }
    
    protected void eraseSingleEntry() {
        singleInputField.setText("");
        singleOutputField.setText("");
    }

    void cancelTable() {
        makeTableFlag = false;
        tableProgressBar.setValue(0);
        dblList
                = new ArrayList<Double[]>();
    }

    String getFormattedTable(int tableType) {
        String result = "";
        switch (tableType) {
            case Constants.TABLEPLAIN:
                result = buildPlainTextTable();
                break;
            case Constants.TABLETSV:
                result = buildTSVTable();
                break;
            case Constants.TABLEHTML:
                result = buildHTMLTable(mostRecentTableType);
                break;
        }
        return result;
    }

    String createEndCapLabel(boolean leftCap) {
        double a = (leftCap) ? tankProcessor.g_rL : tankProcessor.g_rR;
        double b = (leftCap) ? tankProcessor.leftMajorSphereRadius : tankProcessor.rightMajorSphereRadius;
        return formatNum(tankProcessor.convertLengthUnits(a, true)) + "/" + formatNum(tankProcessor.convertLengthUnits(b, true));
    }

    protected String tankOrientationTitle() {
        return Constants.tankOrientationTitles[sharedTP.tankOrientation];
    }

    protected String tankOrientationString() {
        String s = Constants.tankOrientationTitles[sharedTP.tankOrientation];
        if (sharedTP.tankOrientation == Constants.TANKTILTED) {
            s += " (" + formatNum(sharedTP.angleDegrees) + "°)";
        }
        return s;
    }

    ArrayList<String> createTitle(boolean html) {
        ArrayList<String> titleVec = new ArrayList<String>();
        String userTitle = tableTitleTextField.getText();
        if (userTitle.length() > 0) {
            titleVec.add(userTitle);
        }
        return titleVec;
    }

    String joinVec(ArrayList<String> v, String token) {
        StringBuilder sb = new StringBuilder();
        Iterator<String> it = v.iterator();
        boolean first = true;
        while (it.hasNext()) {
            if (!first) {
                sb.append(token);
            }
            sb.append(it.next());
            first = false;
        }

        return sb.toString();
    }

    void addLine(StringBuilder sb, ArrayList<String> fields) {
        int i = 0;
        for (String s : fields) {
            s = s.replaceAll("&sup(\\d);", "^$1");
            sb.append(String.format("%" + intColumnWidths[i] + "s", s));
            i++;
        }
        sb.append("\n");
    }

    String buildPlainTextTable() {
        String s;
        StringBuilder sb = new StringBuilder();
        StringBuilder underscore = new StringBuilder();
        int fullWidth = 0;
        for (int width : intColumnWidths) {
            fullWidth += width;
            for (int j = 0; j < width; j++) {
                underscore.append("-");
            }
        }
        String title = tableTitleTextField.getText() + "\n";
        int delta = (fullWidth + title.length()) / 2;
        sb.append(String.format("%" + delta + "s", title));
        sb.append("\n\n");
        boolean needUnderscore = true;
        ArrayList<ArrayList<String>> list = new ArrayList<>();
        list.add(strHeaderArray);
        list.addAll(strTableArray);
        for (ArrayList<String> array : list) {
            addLine(sb, array);
            if (needUnderscore) {
                sb.append(underscore).append("\n");
                needUnderscore = false;
            }
        }
        return (sb.toString());
    }

    String buildTSVTable() {
        StringBuilder sb = new StringBuilder();
        String title = tableTitleTextField.getText() + "\n";
        title = title.replaceAll(",", " -");
        sb.append(title);
        sb.append("\n\n");
        ArrayList<ArrayList<String>> list = new ArrayList<>();
        list.add(strHeaderArray);
        list.addAll(strTableArray);
        for (ArrayList<String> array : list) {
            String row = buildTSVRow(array);
            sb.append(row);
        }
        return (sb.toString());
    }
    
    String buildTSVRow(ArrayList<String> array) {
        StringBuilder ssb = new StringBuilder();
        int i = 0;
            for (String ss : array) {
                if (i > 0) {
                    ssb.append("\t");
                }
                ssb.append(ss);
                i++;
            }
            ssb.append("\n");
            return plainTextConvertExponents(ssb.toString());
    }
        

    // all this struggle because Java doesn't have
    // either here-docs or join()
    String[] tableCSS = {
        "<style type=\"text/css\">",
        "body {font-family: Verdana, Tahoma, Helvetica, Arial;}",
        "table {",
        "border-top:1px solid black;",
        "border-right:1px solid black;",
        "border-bottom:1px solid black;",
        "}",
        "td {",
        "border-left:1px solid black;",
        "padding-right:4px;",
        "padding-left:4px;",
        "}",
        "th {",
        "text-align:center;",
        "border-left:1px solid black;",
        "border-bottom:1px solid black;",
        "background:#ffffe0;",
        "font-weight: bold;",
        "vertical-align:bottom;",
        "padding:4px;",
        "}",
        ".cell0 { text-align:right; background:#f0f0f0; }",
        ".cell1 { text-align:right; background:white; }",
        "</style>"
    };

    String getCSS() {

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i
                < tableCSS.length; i++) {
            sb.append(tableCSS[i]);
            sb.append("\n");
        }
        return sb.toString();
    }

    String wrapTag(String tag, String content, String extra) {
        return "<" + tag + ((extra.length() > 0) ? " " + extra : "") + ">" + content + "</" + tag + ">\n";
    }

    String wrapTag(String tag, String content) {
        return wrapTag(tag, content, "");
    }

    String buildHTMLTable(int type) {
        StringBuilder sb = new StringBuilder();
        String banner = "";

        String vs = sharedTP.tableTitle;
        if (vs.length() > 0) {
            banner = vs;
            banner = wrapTag("b", banner);
            banner = wrapTag("p", banner);
        }
        String title = vs;
        String headTitle = title.replaceAll("\n+", " -- ");
        headTitle = wrapTag("title", headTitle);
        String head = wrapTag("head", headTitle + "\n" + getCSS());
        int i = 0;
        String s = "";
        ArrayList<ArrayList<String>> list = new ArrayList<>();
        list.add(strHeaderArray);
        list.addAll(strTableArray);
        for (ArrayList<String> array : list) {
            int row = i % 2;
            String css = "class=\"cell" + row + "\"";
            for (String ss : array) {
                ss = ss.replaceFirst("\\^(\\d)", "<sup>$1</sup>");
                s += wrapTag((i == 0) ? "th" : "td", ss);
            }
            sb.append(wrapTag("tr", s, css));
            s = "";
            i++;
        }
        String body = wrapTag("table", sb.toString(), "cellpadding=\"2\" cellspacing=\"0\" border=\"0\"");
        String explain = "";
        // if this is a data table
        if (type == 0) {
            explain = "<b>LV</b> = Liquid Volume<br/>";
            explain += "<b>LWA</b> = Liquid Wetted Area (liquid/tank interface)<br/>";
            explain += "<b>LSA</b> = Liquid Surface Area (liquid/gas interface)";
            explain = wrapTag("p", explain);
        }
        String source = "Source: " + programName + " " + VERSION + ", Copyright &copy; 2014, P. Lutus<br/>(<a href=\"http://www.arachnoid.com/TankCalc/index.html\">http://www.arachnoid.com/TankCalc</a>)";
        source = wrapTag("p", source);
        explain = wrapTag("div", explain + source, "align=\"center\"");
        s = banner + "<br/>" + body + explain;
        s = head + wrapTag("body", wrapTag("div", s, "align=\"center\""));
        s = wrapTag("html", s);
        //clipboardData = s;
        return s;

    }

    void updateTableDisplay() {
        ((DataTableDisplay) dataTableDisplay).updateDisplay();

    }

    // manageHyperlinks tries to find and launch a browser
    private void manageHyperlinks(HyperlinkEvent evt) {
        //URL url = evt.getURL();
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
            String surl = evt.getURL().toString();
            if (surl.matches("http://.*")) {

                try {
                    java.awt.Desktop.getDesktop().browse(java.net.URI.create(surl));
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
    }

    public void setClipboardContents(String s) {
        StringSelection stringSelection = new StringSelection(s);
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.setContents(stringSelection, this);
    }

    @Override
    public void lostOwnership(Clipboard aClipboard, Transferable aContents) {
        //do nothing
    }

    void copyToClipboard(String s) {
        if (s.length() > 0) {
            if (applet) {
                setStatus("See help on applet clipboard operations.", true);
            }
            setClipboardContents(s);
        } else {
            setStatus("Error: Must create data first.", true);
        }
    }

    void copyTableToClipboard(int type) {
        copyToClipboard(getFormattedTable(type));
    }

    //void copyWeightToClipboard() {
    //    copyToClipboard(massResultTextArea);
    //}
    public void beep() {
        // a way to trace random program beeps
        //System.out.println(getStackTrace());
        Toolkit.getDefaultToolkit().beep();
    }

    void processTabClick() {
        Component comp = mainTabbedPane.getSelectedComponent();
        //comp.requestFocus();
        if (comp == helpPanel) {
            helpPane.findTextField.requestFocusInWindow();
        } else if (comp == graphicModelPanel) {
            mainPanel3d.requestFocusInWindow();
        } else if (comp == tableGenPanel) {
            buildTable(Constants.SPECTABLE,true);
        }
        this.updateGraphicImages();
        sharedTP.currentTab = mainTabbedPane.getSelectedIndex();
    }

    public String getConfig() {
        if (initManager != null) {
            helpScrollPos = helpPane.getScrollPos();
            return initManager.getConfig();
        } else {
            return null;
        }
    }

    public void setConfig(String data) {
        initManager.setConfig(data);
        //enabled = true;
        setModeAndLabels();
        mainPanel3d.updateSettings(sharedTP);
        processTabClick();
        SwingUtilities.invokeLater(
                new Runnable() {

                    @Override
                    public void run() {
                        helpPane.setScrollPos(helpScrollPos);
                    }
                });
    }

    void manageHelpSlides(int n) {
        helpSlideIndex += n;
        if (helpSlideIndex < 0) {
            helpSlideIndex = 0;
            beep();

        }
        if (helpSlideIndex > helpSlides.length - 1) {
            helpSlideIndex = helpSlides.length - 1;
            beep();

        }
        ghBackButton.setEnabled(helpSlideIndex > 0);
        ghForwardButton.setEnabled(helpSlideIndex < helpSlides.length - 1);
        URL url = getClass().getResource("help_slides/" + helpSlides[helpSlideIndex]);
        Image appIcon = new ImageIcon(url).getImage();
        helpSlideLabel.setIcon(new ImageIcon(appIcon));
    }

    String readResourceFile(String fn) {
        String s = "";
        try {
            InputStream is = getClass().getResourceAsStream(fn);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            StringBuilder sb = new StringBuilder();
            String line;

            while ((line = br.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }

            is.close();
            s
                    = sb.toString();
        } catch (Exception e) {
            System.out.println("readResourceFile: " + e);
        }

        return s;
    }

    void updateGraphicImages() {
        if (mainPanel3d != null) {
            mainPanel3d.createTankImage(sharedTP);
        }
        if (subPanel3d != null) {
            subPanel3d.createTankImage(sharedTP);
        }
    }

    public void close() {
        if (!applet) {
            helpScrollPos = helpPane.getScrollPos();
            initManager.writeConfig();
        }
        setVisible(false);
        System.exit(0);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        NormalInversebuttonGroup = new javax.swing.ButtonGroup();
        tableTypeButtonGroup = new javax.swing.ButtonGroup();
        mainTabbedPane = new javax.swing.JTabbedPane();
        inputPanel = new javax.swing.JPanel();
        viewPanel = new javax.swing.JPanel();
        unitsSubPanel = new javax.swing.JPanel();
        copyDescButton = new javax.swing.JButton();
        pasteDescButton = new javax.swing.JButton();
        resetButton = new javax.swing.JButton();
        jScrollPane5 = new javax.swing.JScrollPane();
        entryPanel = new javax.swing.JPanel();
        LVariableLabel = new javax.swing.JLabel();
        g_LTextField = new javax.swing.JTextField();
        RVariableLabel = new javax.swing.JLabel();
        g_RTextField = new javax.swing.JTextField();
        lbVariableLabel1 = new javax.swing.JLabel();
        lbVariableLabel2 = new javax.swing.JLabel();
        g_rLTextField = new javax.swing.JTextField();
        rtVariableLabel1 = new javax.swing.JLabel();
        rtVariableLabel2 = new javax.swing.JLabel();
        g_rRTextField = new javax.swing.JTextField();
        leftCapComboBox = new javax.swing.JComboBox();
        rightCapComboBox = new javax.swing.JComboBox();
        scaling_factor_label = new javax.swing.JLabel();
        scalingFactorTextField = new javax.swing.JTextField();
        jLabel19 = new javax.swing.JLabel();
        tankOrientationComboBox = new javax.swing.JComboBox();
        tankAngleLabel = new javax.swing.JLabel();
        tankAngleTextField = new javax.swing.JTextField();
        sensorPathLabel = new javax.swing.JLabel();
        sensorOrientationComboBox = new javax.swing.JComboBox();
        xCoordLabel = new javax.swing.JLabel();
        yCoordLabel = new javax.swing.JLabel();
        zCoordLabel = new javax.swing.JLabel();
        sensorXTextField = new javax.swing.JTextField();
        sensorYTextField = new javax.swing.JTextField();
        sensorZTextField = new javax.swing.JTextField();
        residVolumeLabel = new javax.swing.JLabel();
        residVolumeTextField = new javax.swing.JTextField();
        wallThicknessLabel = new javax.swing.JLabel();
        jLabel20 = new javax.swing.JLabel();
        jLabel21 = new javax.swing.JLabel();
        wallThicknessTextField = new javax.swing.JTextField();
        wallDensityTextField = new javax.swing.JTextField();
        contentDensityTextField = new javax.swing.JTextField();
        inputTag = new javax.swing.JLabel();
        inputUnitsComboBox = new javax.swing.JComboBox<String>();
        outputTag = new javax.swing.JLabel();
        outputUnitsComboBox = new javax.swing.JComboBox<String>();
        jLabel18 = new javax.swing.JLabel();
        weightUnitsComboBox = new javax.swing.JComboBox();
        jLabel9 = new javax.swing.JLabel();
        cylinderIntegrationStepsTextField = new javax.swing.JTextField();
        jLabel10 = new javax.swing.JLabel();
        endCapIntegrationStepsTextField = new javax.swing.JTextField();
        heightStepSizeLabel = new javax.swing.JLabel();
        tableHeightStepSizeTextField = new javax.swing.JTextField();
        volumeStepSizeLabel = new javax.swing.JLabel();
        jLabel11 = new javax.swing.JLabel();
        tableVolumeStepSizeTextField = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        decimalPlacesComboBox = new javax.swing.JComboBox<Integer>();
        rootFinderEpsilonTextField = new javax.swing.JTextField();
        tableGenPanel = new javax.swing.JPanel();
        SingleResultPanel = new javax.swing.JPanel();
        modePanel = new javax.swing.JPanel();
        inputLabel = new javax.swing.JLabel();
        singleInputField = new javax.swing.JTextField();
        outputLabel = new javax.swing.JLabel();
        singleOutputField = new javax.swing.JTextField();
        TablePanel = new javax.swing.JPanel();
        tableControlPanel = new javax.swing.JPanel();
        copyHTMLToClipboardButton = new javax.swing.JButton();
        tableCancelButton = new javax.swing.JButton();
        buildVHDataTableButton = new javax.swing.JButton();
        buildHVDataTableButton = new javax.swing.JButton();
        buildSpecTableButton = new javax.swing.JButton();
        copyTSVToClipboardButton = new javax.swing.JButton();
        copyPlainToClipboardButton = new javax.swing.JButton();
        fillerPanel = new javax.swing.JPanel();
        tableProgressBar = new javax.swing.JProgressBar();
        jPanel3 = new javax.swing.JPanel();
        jLabel6 = new javax.swing.JLabel();
        tableTitleTextField = new javax.swing.JTextField();
        tableDisplayPanel = new javax.swing.JPanel();
        tableScrollPane = new javax.swing.JScrollPane();
        dataTableDisplay = new DataTableDisplay(this);
        graphicModelPanel = new javax.swing.JPanel();
        graphicDisplayPanel = new javax.swing.JPanel();
        controlPanelA = new javax.swing.JPanel();
        inverseCheckBox = new javax.swing.JCheckBox();
        leftCapCheckBox = new javax.swing.JCheckBox();
        cylinderCheckBox = new javax.swing.JCheckBox();
        rightCapCheckBox = new javax.swing.JCheckBox();
        sensorCheckBox = new javax.swing.JCheckBox();
        lineThicknessLabel = new javax.swing.JLabel();
        lineThicknessComboBox = new javax.swing.JComboBox<Integer>();
        jLabel3 = new javax.swing.JLabel();
        anaglyphicLabel = new javax.swing.JLabel();
        anaglyphCheckBox = new javax.swing.JCheckBox();
        controlPanelB = new javax.swing.JPanel();
        jLabel12 = new javax.swing.JLabel();
        xLinesComboBox = new javax.swing.JComboBox<Integer>();
        jLabel13 = new javax.swing.JLabel();
        yLinesComboBox = new javax.swing.JComboBox<Integer>();
        polygonCheckBox = new javax.swing.JCheckBox();
        transparencyLabel = new javax.swing.JLabel();
        transparencyComboBox = new javax.swing.JComboBox<Integer>();
        antialiasingCheckBox = new javax.swing.JCheckBox();
        graphicDefaultsButton = new javax.swing.JButton();
        copyButton = new javax.swing.JButton();
        graphicPanel = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        helpSlideLabel = new javax.swing.JLabel();
        graphicHelpControls = new javax.swing.JPanel();
        ghBackButton = new javax.swing.JButton();
        ghForwardButton = new javax.swing.JButton();
        helpPanel = new javax.swing.JPanel();
        statusPanel = new javax.swing.JPanel();
        statusLabel = new javax.swing.JLabel();
        debug_label = new javax.swing.JLabel();

        setFocusable(false);
        setMinimumSize(new java.awt.Dimension(400, 300));
        setPreferredSize(new java.awt.Dimension(800, 600));
        setLayout(new java.awt.GridBagLayout());

        mainTabbedPane.setTabPlacement(javax.swing.JTabbedPane.BOTTOM);
        mainTabbedPane.setFocusable(false);
        mainTabbedPane.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                mainTabbedPaneMouseClicked(evt);
            }
        });

        inputPanel.setFocusable(false);
        inputPanel.setMinimumSize(new java.awt.Dimension(382, 260));
        inputPanel.setPreferredSize(new java.awt.Dimension(382, 260));
        inputPanel.setLayout(new java.awt.GridBagLayout());

        viewPanel.setBackground(java.awt.Color.white);
        viewPanel.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        inputPanel.add(viewPanel, gridBagConstraints);

        unitsSubPanel.setLayout(new java.awt.GridBagLayout());

        copyDescButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/edit-copy.png"))); // NOI18N
        copyDescButton.setText("Copy");
        copyDescButton.setToolTipText("Copy this tank's description to the clipboard");
        copyDescButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                copyDescButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 9;
        gridBagConstraints.gridy = 0;
        unitsSubPanel.add(copyDescButton, gridBagConstraints);

        pasteDescButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/edit-paste.png"))); // NOI18N
        pasteDescButton.setText("Paste");
        pasteDescButton.setToolTipText("Paste a tank description or file name from the clipboard");
        pasteDescButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                pasteDescButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 10;
        gridBagConstraints.gridy = 0;
        unitsSubPanel.add(pasteDescButton, gridBagConstraints);

        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/edit-clear.png"))); // NOI18N
        resetButton.setText("Defaults");
        resetButton.setToolTipText("Reset all entries to default values");
        resetButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                resetButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 8;
        gridBagConstraints.gridy = 0;
        unitsSubPanel.add(resetButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        inputPanel.add(unitsSubPanel, gridBagConstraints);

        jScrollPane5.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        jScrollPane5.setMinimumSize(new java.awt.Dimension(360, 22));
        jScrollPane5.setPreferredSize(new java.awt.Dimension(360, 437));

        entryPanel.setBackground(new java.awt.Color(51, 51, 51));
        entryPanel.setLayout(new java.awt.GridBagLayout());

        LVariableLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        LVariableLabel.setForeground(new java.awt.Color(255, 255, 255));
        LVariableLabel.setText(" Cylinder length (L)");
        LVariableLabel.setIconTextGap(0);
        LVariableLabel.setMaximumSize(new java.awt.Dimension(3000, 24));
        LVariableLabel.setMinimumSize(new java.awt.Dimension(200, 24));
        LVariableLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(LVariableLabel, gridBagConstraints);

        g_LTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        g_LTextField.setText("96.0");
        g_LTextField.setToolTipText("Enter cylinder section length");
        g_LTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        g_LTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        g_LTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        g_LTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                g_LTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(g_LTextField, gridBagConstraints);

        RVariableLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        RVariableLabel.setForeground(new java.awt.Color(255, 255, 255));
        RVariableLabel.setText(" Cylinder radius (R)");
        RVariableLabel.setIconTextGap(0);
        RVariableLabel.setMaximumSize(new java.awt.Dimension(3000, 24));
        RVariableLabel.setMinimumSize(new java.awt.Dimension(200, 24));
        RVariableLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(RVariableLabel, gridBagConstraints);

        g_RTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        g_RTextField.setText("36.0");
        g_RTextField.setToolTipText("Enter cylinder radius");
        g_RTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        g_RTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        g_RTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        g_RTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                g_RTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(g_RTextField, gridBagConstraints);

        lbVariableLabel1.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        lbVariableLabel1.setForeground(new java.awt.Color(255, 255, 255));
        lbVariableLabel1.setText(" Left/Bottom cap radius (r) cm");
        lbVariableLabel1.setIconTextGap(0);
        lbVariableLabel1.setMaximumSize(new java.awt.Dimension(3000, 24));
        lbVariableLabel1.setMinimumSize(new java.awt.Dimension(200, 24));
        lbVariableLabel1.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(lbVariableLabel1, gridBagConstraints);

        lbVariableLabel2.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        lbVariableLabel2.setForeground(new java.awt.Color(255, 255, 255));
        lbVariableLabel2.setText(" Left/Bottom cap type");
        lbVariableLabel2.setIconTextGap(0);
        lbVariableLabel2.setMaximumSize(new java.awt.Dimension(3000, 24));
        lbVariableLabel2.setMinimumSize(new java.awt.Dimension(200, 24));
        lbVariableLabel2.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(lbVariableLabel2, gridBagConstraints);

        g_rLTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        g_rLTextField.setText("18.0");
        g_rLTextField.setToolTipText("Enter left/bottom cap radius (see help on how to make this entry)");
        g_rLTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        g_rLTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        g_rLTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        g_rLTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                g_rLTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(g_rLTextField, gridBagConstraints);

        rtVariableLabel1.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        rtVariableLabel1.setForeground(new java.awt.Color(255, 255, 255));
        rtVariableLabel1.setText(" Right/top cap radius (r) cm ");
        rtVariableLabel1.setIconTextGap(0);
        rtVariableLabel1.setMaximumSize(new java.awt.Dimension(3000, 24));
        rtVariableLabel1.setMinimumSize(new java.awt.Dimension(200, 24));
        rtVariableLabel1.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 6;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(rtVariableLabel1, gridBagConstraints);

        rtVariableLabel2.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        rtVariableLabel2.setForeground(new java.awt.Color(255, 255, 255));
        rtVariableLabel2.setText(" Right/top cap type");
        rtVariableLabel2.setIconTextGap(0);
        rtVariableLabel2.setMaximumSize(new java.awt.Dimension(3000, 24));
        rtVariableLabel2.setMinimumSize(new java.awt.Dimension(200, 24));
        rtVariableLabel2.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 7;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(rtVariableLabel2, gridBagConstraints);

        g_rRTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        g_rRTextField.setText("18.0");
        g_rRTextField.setToolTipText("Enter right/top cap radius (see help on how to make this entry)");
        g_rRTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        g_rRTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        g_rRTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        g_rRTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                g_rRTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 6;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(g_rRTextField, gridBagConstraints);

        leftCapComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Elliptical", "Conical", "Spherical" }));
        leftCapComboBox.setToolTipText("Enter left/bottom end cap type");
        leftCapComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                leftCapComboBoxItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(leftCapComboBox, gridBagConstraints);

        rightCapComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Elliptical", "Conical", "Spherical" }));
        rightCapComboBox.setToolTipText("Enter right/top end cap type");
        rightCapComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                rightCapComboBoxItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 7;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(rightCapComboBox, gridBagConstraints);

        scaling_factor_label.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        scaling_factor_label.setForeground(new java.awt.Color(255, 255, 255));
        scaling_factor_label.setText("Scaling Factor");
        scaling_factor_label.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 13;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(scaling_factor_label, gridBagConstraints);

        scalingFactorTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        scalingFactorTextField.setText("1.0");
        scalingFactorTextField.setToolTipText("Scaling factor for oval cross-section tanks");
        scalingFactorTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        scalingFactorTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        scalingFactorTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        scalingFactorTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                scalingFactorTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 13;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(scalingFactorTextField, gridBagConstraints);

        jLabel19.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        jLabel19.setForeground(new java.awt.Color(255, 255, 255));
        jLabel19.setText(" Tank orientation");
        jLabel19.setIconTextGap(0);
        jLabel19.setMaximumSize(new java.awt.Dimension(3000, 24));
        jLabel19.setMinimumSize(new java.awt.Dimension(200, 24));
        jLabel19.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 14;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(jLabel19, gridBagConstraints);

        tankOrientationComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Horizontal", "Vertical", "Tilted" }));
        tankOrientationComboBox.setToolTipText("Select tank orientation");
        tankOrientationComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                tankOrientationComboBoxItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 14;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(tankOrientationComboBox, gridBagConstraints);

        tankAngleLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        tankAngleLabel.setForeground(new java.awt.Color(255, 255, 255));
        tankAngleLabel.setText(" Tank angle degrees (or slope %)");
        tankAngleLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tankAngleLabel.setIconTextGap(0);
        tankAngleLabel.setMaximumSize(new java.awt.Dimension(200, 24));
        tankAngleLabel.setMinimumSize(new java.awt.Dimension(200, 24));
        tankAngleLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 15;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(tankAngleLabel, gridBagConstraints);

        tankAngleTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        tankAngleTextField.setText("5%");
        tankAngleTextField.setToolTipText("<html>Enter angle in degrees (0-90) or slope in percent<br/>\n(use percent % sign for slope)</html>");
        tankAngleTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        tankAngleTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        tankAngleTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        tankAngleTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                tankAngleTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 15;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(tankAngleTextField, gridBagConstraints);

        sensorPathLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        sensorPathLabel.setForeground(new java.awt.Color(255, 255, 255));
        sensorPathLabel.setText(" Sensor axis");
        sensorPathLabel.setIconTextGap(0);
        sensorPathLabel.setMaximumSize(new java.awt.Dimension(3000, 25));
        sensorPathLabel.setMinimumSize(new java.awt.Dimension(200, 24));
        sensorPathLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 16;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(sensorPathLabel, gridBagConstraints);

        sensorOrientationComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Contents", "Y axis", "X axis" }));
        sensorOrientationComboBox.setToolTipText("Sensor is perpendicular to this axis");
        sensorOrientationComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                sensorOrientationComboBoxItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 16;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(sensorOrientationComboBox, gridBagConstraints);

        xCoordLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        xCoordLabel.setForeground(new java.awt.Color(255, 255, 255));
        xCoordLabel.setText(" Sensor X position cm");
        xCoordLabel.setIconTextGap(0);
        xCoordLabel.setMaximumSize(new java.awt.Dimension(3000, 24));
        xCoordLabel.setMinimumSize(new java.awt.Dimension(200, 24));
        xCoordLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 17;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(xCoordLabel, gridBagConstraints);

        yCoordLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        yCoordLabel.setForeground(new java.awt.Color(255, 255, 255));
        yCoordLabel.setText(" Sensor Y position cm");
        yCoordLabel.setIconTextGap(0);
        yCoordLabel.setMaximumSize(new java.awt.Dimension(3000, 24));
        yCoordLabel.setMinimumSize(new java.awt.Dimension(200, 24));
        yCoordLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 18;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(yCoordLabel, gridBagConstraints);

        zCoordLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        zCoordLabel.setForeground(new java.awt.Color(255, 255, 255));
        zCoordLabel.setText(" Sensor Z position cm");
        zCoordLabel.setIconTextGap(0);
        zCoordLabel.setMaximumSize(new java.awt.Dimension(3000, 24));
        zCoordLabel.setMinimumSize(new java.awt.Dimension(200, 24));
        zCoordLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 19;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(zCoordLabel, gridBagConstraints);

        sensorXTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        sensorXTextField.setText("0.0");
        sensorXTextField.setToolTipText("Enter the sensor's X (left/right) position");
        sensorXTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        sensorXTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        sensorXTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        sensorXTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                sensorXTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 17;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(sensorXTextField, gridBagConstraints);

        sensorYTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        sensorYTextField.setText("0.0");
        sensorYTextField.setToolTipText("Enter the sensor's Y (up/down) position");
        sensorYTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        sensorYTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        sensorYTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        sensorYTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                sensorYTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 18;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(sensorYTextField, gridBagConstraints);

        sensorZTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        sensorZTextField.setText("0.0");
        sensorZTextField.setToolTipText("Enter the sensor's Z (front/back) position");
        sensorZTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        sensorZTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        sensorZTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        sensorZTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                sensorZTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 19;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(sensorZTextField, gridBagConstraints);

        residVolumeLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        residVolumeLabel.setForeground(new java.awt.Color(255, 255, 255));
        residVolumeLabel.setText(" Residual Volume");
        residVolumeLabel.setIconTextGap(0);
        residVolumeLabel.setMaximumSize(new java.awt.Dimension(3000, 24));
        residVolumeLabel.setMinimumSize(new java.awt.Dimension(200, 24));
        residVolumeLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 20;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(residVolumeLabel, gridBagConstraints);

        residVolumeTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        residVolumeTextField.setText("0.0");
        residVolumeTextField.setToolTipText("Enter volume to adjust for inaccessible/unmeasured content");
        residVolumeTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        residVolumeTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        residVolumeTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        residVolumeTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                residVolumeTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 20;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(residVolumeTextField, gridBagConstraints);

        wallThicknessLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        wallThicknessLabel.setForeground(new java.awt.Color(255, 255, 255));
        wallThicknessLabel.setText(" Wall thickness");
        wallThicknessLabel.setIconTextGap(0);
        wallThicknessLabel.setMaximumSize(new java.awt.Dimension(3000, 24));
        wallThicknessLabel.setMinimumSize(new java.awt.Dimension(200, 24));
        wallThicknessLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 21;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(wallThicknessLabel, gridBagConstraints);

        jLabel20.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        jLabel20.setForeground(new java.awt.Color(255, 255, 255));
        jLabel20.setText(" Wall material density");
        jLabel20.setIconTextGap(0);
        jLabel20.setMaximumSize(new java.awt.Dimension(3000, 24));
        jLabel20.setMinimumSize(new java.awt.Dimension(200, 24));
        jLabel20.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 22;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(jLabel20, gridBagConstraints);

        jLabel21.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        jLabel21.setForeground(new java.awt.Color(255, 255, 255));
        jLabel21.setText(" Content density");
        jLabel21.setIconTextGap(0);
        jLabel21.setMaximumSize(new java.awt.Dimension(3000, 24));
        jLabel21.setMinimumSize(new java.awt.Dimension(200, 24));
        jLabel21.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 23;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(jLabel21, gridBagConstraints);

        wallThicknessTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        wallThicknessTextField.setText("0.1");
        wallThicknessTextField.setToolTipText("Enter tank wall thickness");
        wallThicknessTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        wallThicknessTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        wallThicknessTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        wallThicknessTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                wallThicknessTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 21;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(wallThicknessTextField, gridBagConstraints);

        wallDensityTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        wallDensityTextField.setText("8.03");
        wallDensityTextField.setToolTipText("Enter tank wall density value (water = 1, steel = 8.03)");
        wallDensityTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        wallDensityTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        wallDensityTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        wallDensityTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                wallDensityTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 22;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(wallDensityTextField, gridBagConstraints);

        contentDensityTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        contentDensityTextField.setText("0.70");
        contentDensityTextField.setToolTipText("Enter tank content density value (water = 1)");
        contentDensityTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        contentDensityTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        contentDensityTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        contentDensityTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                contentDensityTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 23;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(contentDensityTextField, gridBagConstraints);

        inputTag.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        inputTag.setForeground(new java.awt.Color(255, 255, 255));
        inputTag.setText(" Length Units");
        inputTag.setIconTextGap(0);
        inputTag.setMaximumSize(new java.awt.Dimension(3000, 24));
        inputTag.setMinimumSize(new java.awt.Dimension(200, 24));
        inputTag.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 24;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(inputTag, gridBagConstraints);

        inputUnitsComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        inputUnitsComboBox.setToolTipText("Select tank dimension length units");
        inputUnitsComboBox.setFocusable(false);
        inputUnitsComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                inputUnitsComboBoxItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 24;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(inputUnitsComboBox, gridBagConstraints);

        outputTag.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        outputTag.setForeground(new java.awt.Color(255, 255, 255));
        outputTag.setText(" Volume Units");
        outputTag.setIconTextGap(0);
        outputTag.setMaximumSize(new java.awt.Dimension(3000, 24));
        outputTag.setMinimumSize(new java.awt.Dimension(200, 24));
        outputTag.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 25;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(outputTag, gridBagConstraints);

        outputUnitsComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        outputUnitsComboBox.setToolTipText("Select tank content volume units");
        outputUnitsComboBox.setFocusable(false);
        outputUnitsComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                outputUnitsComboBoxItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 25;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(outputUnitsComboBox, gridBagConstraints);

        jLabel18.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        jLabel18.setForeground(new java.awt.Color(255, 255, 255));
        jLabel18.setText(" Weight units");
        jLabel18.setIconTextGap(0);
        jLabel18.setMaximumSize(new java.awt.Dimension(3000, 24));
        jLabel18.setMinimumSize(new java.awt.Dimension(200, 24));
        jLabel18.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 26;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(jLabel18, gridBagConstraints);

        weightUnitsComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "kilograms", "pounds" }));
        weightUnitsComboBox.setSelectedIndex(1);
        weightUnitsComboBox.setToolTipText("Select weight units");
        weightUnitsComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                weightUnitsComboBoxItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 26;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(weightUnitsComboBox, gridBagConstraints);

        jLabel9.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        jLabel9.setForeground(new java.awt.Color(255, 255, 255));
        jLabel9.setText(" Cylinder integration steps");
        jLabel9.setIconTextGap(0);
        jLabel9.setMaximumSize(new java.awt.Dimension(3000, 24));
        jLabel9.setMinimumSize(new java.awt.Dimension(200, 24));
        jLabel9.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 28;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(jLabel9, gridBagConstraints);

        cylinderIntegrationStepsTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        cylinderIntegrationStepsTextField.setText("200");
        cylinderIntegrationStepsTextField.setToolTipText("The number of steps to integrate the cylinder's volume");
        cylinderIntegrationStepsTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        cylinderIntegrationStepsTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        cylinderIntegrationStepsTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        cylinderIntegrationStepsTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                cylinderIntegrationStepsTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 28;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(cylinderIntegrationStepsTextField, gridBagConstraints);

        jLabel10.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        jLabel10.setForeground(new java.awt.Color(255, 255, 255));
        jLabel10.setText(" End cap integration steps");
        jLabel10.setIconTextGap(0);
        jLabel10.setMaximumSize(new java.awt.Dimension(3000, 24));
        jLabel10.setMinimumSize(new java.awt.Dimension(200, 24));
        jLabel10.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 29;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(jLabel10, gridBagConstraints);

        endCapIntegrationStepsTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        endCapIntegrationStepsTextField.setText("400");
        endCapIntegrationStepsTextField.setToolTipText("The number of steps to integrate each end cap's volume");
        endCapIntegrationStepsTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        endCapIntegrationStepsTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        endCapIntegrationStepsTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        endCapIntegrationStepsTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                endCapIntegrationStepsTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 29;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(endCapIntegrationStepsTextField, gridBagConstraints);

        heightStepSizeLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        heightStepSizeLabel.setForeground(new java.awt.Color(255, 255, 255));
        heightStepSizeLabel.setText(" Height Table Step Size");
        heightStepSizeLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 30;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(heightStepSizeLabel, gridBagConstraints);

        tableHeightStepSizeTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        tableHeightStepSizeTextField.setText("1.0");
        tableHeightStepSizeTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 30;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(tableHeightStepSizeTextField, gridBagConstraints);

        volumeStepSizeLabel.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        volumeStepSizeLabel.setForeground(new java.awt.Color(255, 255, 255));
        volumeStepSizeLabel.setText(" Volume Table Step Size");
        volumeStepSizeLabel.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 31;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(volumeStepSizeLabel, gridBagConstraints);

        jLabel11.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        jLabel11.setForeground(new java.awt.Color(255, 255, 255));
        jLabel11.setText(" Root finder epsilon");
        jLabel11.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 32;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(jLabel11, gridBagConstraints);

        tableVolumeStepSizeTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        tableVolumeStepSizeTextField.setText("1.0");
        tableVolumeStepSizeTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        tableVolumeStepSizeTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        tableVolumeStepSizeTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 31;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(tableVolumeStepSizeTextField, gridBagConstraints);

        jLabel5.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        jLabel5.setForeground(new java.awt.Color(255, 255, 255));
        jLabel5.setText(" Displayed Decimal Places  ");
        jLabel5.setPreferredSize(new java.awt.Dimension(240, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 27;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        entryPanel.add(jLabel5, gridBagConstraints);

        decimalPlacesComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        decimalPlacesComboBox.setToolTipText("Number resolution");
        decimalPlacesComboBox.setMinimumSize(new java.awt.Dimension(40, 24));
        decimalPlacesComboBox.setPreferredSize(new java.awt.Dimension(10, 24));
        decimalPlacesComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                decimalPlacesComboBoxItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 27;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(decimalPlacesComboBox, gridBagConstraints);

        rootFinderEpsilonTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        rootFinderEpsilonTextField.setText("1e-8");
        rootFinderEpsilonTextField.setToolTipText("The accuracy specifier for the height-from-volume root finder");
        rootFinderEpsilonTextField.setMaximumSize(new java.awt.Dimension(150, 24));
        rootFinderEpsilonTextField.setMinimumSize(new java.awt.Dimension(24, 24));
        rootFinderEpsilonTextField.setPreferredSize(new java.awt.Dimension(24, 24));
        rootFinderEpsilonTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                rootFinderEpsilonTextFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 32;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        entryPanel.add(rootFinderEpsilonTextField, gridBagConstraints);

        jScrollPane5.setViewportView(entryPanel);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weighty = 1.0;
        inputPanel.add(jScrollPane5, gridBagConstraints);

        mainTabbedPane.addTab("Input", new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/accessories-text-editor.png")), inputPanel); // NOI18N

        tableGenPanel.setFocusable(false);
        tableGenPanel.setLayout(new java.awt.GridBagLayout());

        SingleResultPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Single Result"));
        SingleResultPanel.setLayout(new java.awt.GridBagLayout());

        modePanel.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        SingleResultPanel.add(modePanel, gridBagConstraints);

        inputLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        inputLabel.setText("jLabel4");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 8;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 16, 4, 4);
        SingleResultPanel.add(inputLabel, gridBagConstraints);

        singleInputField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        singleInputField.setToolTipText("Enter a value, then press Enter");
        singleInputField.setMargin(new java.awt.Insets(0, 4, 0, 4));
        singleInputField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                singleInputFieldKeyTyped(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        SingleResultPanel.add(singleInputField, gridBagConstraints);

        outputLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        outputLabel.setText("jLabel5");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 8;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(4, 16, 4, 4);
        SingleResultPanel.add(outputLabel, gridBagConstraints);

        singleOutputField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        singleOutputField.setToolTipText("Single result appears here");
        singleOutputField.setMargin(new java.awt.Insets(0, 4, 0, 4));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 1.0;
        SingleResultPanel.add(singleOutputField, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        tableGenPanel.add(SingleResultPanel, gridBagConstraints);

        TablePanel.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true));
        TablePanel.setLayout(new java.awt.GridBagLayout());

        tableControlPanel.setLayout(new java.awt.GridBagLayout());

        copyHTMLToClipboardButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/edit-copy.png"))); // NOI18N
        copyHTMLToClipboardButton.setText("Copy HTML");
        copyHTMLToClipboardButton.setToolTipText("Copy table to system clipboard as HTML");
        copyHTMLToClipboardButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                copyHTMLToClipboardButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 0.5;
        tableControlPanel.add(copyHTMLToClipboardButton, gridBagConstraints);

        tableCancelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/process-stop.png"))); // NOI18N
        tableCancelButton.setText("Cancel");
        tableCancelButton.setToolTipText("Cancel current table build");
        tableCancelButton.setEnabled(false);
        tableCancelButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                tableCancelButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 7;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 0.5;
        tableControlPanel.add(tableCancelButton, gridBagConstraints);

        buildVHDataTableButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/system-run.png"))); // NOI18N
        buildVHDataTableButton.setText("Volume -> Height");
        buildVHDataTableButton.setToolTipText("Set volume -> height mode, create table (slower)");
        buildVHDataTableButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                buildVHDataTableButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 0.5;
        tableControlPanel.add(buildVHDataTableButton, gridBagConstraints);

        buildHVDataTableButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/system-run.png"))); // NOI18N
        buildHVDataTableButton.setText("Height -> Volume");
        buildHVDataTableButton.setToolTipText("Set height -> volume mode, create table");
        buildHVDataTableButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                buildHVDataTableButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 0.5;
        tableControlPanel.add(buildHVDataTableButton, gridBagConstraints);

        buildSpecTableButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/accessories-text-editor.png"))); // NOI18N
        buildSpecTableButton.setText("Properties");
        buildSpecTableButton.setToolTipText("Build properties table with current settings");
        buildSpecTableButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                buildSpecTableButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 0.5;
        tableControlPanel.add(buildSpecTableButton, gridBagConstraints);

        copyTSVToClipboardButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/edit-copy.png"))); // NOI18N
        copyTSVToClipboardButton.setText("Copy TSV");
        copyTSVToClipboardButton.setToolTipText("Copy table to system clipboard as tab-separated values (TSV)");
        copyTSVToClipboardButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                copyTSVToClipboardButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 0.5;
        tableControlPanel.add(copyTSVToClipboardButton, gridBagConstraints);

        copyPlainToClipboardButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/edit-copy.png"))); // NOI18N
        copyPlainToClipboardButton.setText("Copy Plain");
        copyPlainToClipboardButton.setToolTipText("Copy table to system clipboard as plain text");
        copyPlainToClipboardButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                copyPlainToClipboardButtonMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 6;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 0.5;
        tableControlPanel.add(copyPlainToClipboardButton, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 8;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 1.0;
        tableControlPanel.add(fillerPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weighty = 1.0;
        TablePanel.add(tableControlPanel, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
        TablePanel.add(tableProgressBar, gridBagConstraints);

        jPanel3.setLayout(new java.awt.GridBagLayout());

        jLabel6.setText(" Table Title  ");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(0, 2, 0, 2);
        jPanel3.add(jLabel6, gridBagConstraints);

        tableTitleTextField.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        tableTitleTextField.setToolTipText("Enter an optional table title");
        tableTitleTextField.setPreferredSize(new java.awt.Dimension(4, 24));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        jPanel3.add(tableTitleTextField, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 0);
        TablePanel.add(jPanel3, gridBagConstraints);

        tableDisplayPanel.setLayout(new java.awt.BorderLayout());

        tableScrollPane.setBackground(new java.awt.Color(255, 255, 255));

        dataTableDisplay.setFont(new java.awt.Font("Courier", 0, 12)); // NOI18N
        dataTableDisplay.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        dataTableDisplay.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
        dataTableDisplay.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        tableScrollPane.setViewportView(dataTableDisplay);

        tableDisplayPanel.add(tableScrollPane, java.awt.BorderLayout.CENTER);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        TablePanel.add(tableDisplayPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        tableGenPanel.add(TablePanel, gridBagConstraints);

        mainTabbedPane.addTab("Compute", new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/TankCalcIcon.png")), tableGenPanel); // NOI18N

        graphicModelPanel.setLayout(new java.awt.GridBagLayout());

        graphicDisplayPanel.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        graphicModelPanel.add(graphicDisplayPanel, gridBagConstraints);

        inverseCheckBox.setText("Inverse");
        inverseCheckBox.setToolTipText("Dark background");
        inverseCheckBox.setFocusable(false);
        inverseCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                inverseCheckBoxMouseClicked(evt);
            }
        });
        controlPanelA.add(inverseCheckBox);

        leftCapCheckBox.setSelected(true);
        leftCapCheckBox.setText("Left Cap");
        leftCapCheckBox.setToolTipText("Draw the left tank cap");
        leftCapCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                leftCapCheckBoxMouseClicked(evt);
            }
        });
        controlPanelA.add(leftCapCheckBox);

        cylinderCheckBox.setSelected(true);
        cylinderCheckBox.setText("Cylinder");
        cylinderCheckBox.setToolTipText("Draw the tank central cylinder");
        cylinderCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                cylinderCheckBoxMouseClicked(evt);
            }
        });
        controlPanelA.add(cylinderCheckBox);

        rightCapCheckBox.setSelected(true);
        rightCapCheckBox.setText("Right Cap");
        rightCapCheckBox.setToolTipText("Draw the tank right cap");
        rightCapCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                rightCapCheckBoxMouseClicked(evt);
            }
        });
        controlPanelA.add(rightCapCheckBox);

        sensorCheckBox.setSelected(true);
        sensorCheckBox.setText("Sensor");
        sensorCheckBox.setToolTipText("Draw the tank content sensor");
        sensorCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                sensorCheckBoxMouseClicked(evt);
            }
        });
        controlPanelA.add(sensorCheckBox);

        lineThicknessLabel.setText("| Line:");
        controlPanelA.add(lineThicknessLabel);

        lineThicknessComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        lineThicknessComboBox.setToolTipText("Line Thickness");
        lineThicknessComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                lineThicknessComboBoxActionPerformed(evt);
            }
        });
        controlPanelA.add(lineThicknessComboBox);

        jLabel3.setText("|");
        controlPanelA.add(jLabel3);

        anaglyphicLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        anaglyphicLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/glasses_3d_pic_small.png"))); // NOI18N
        controlPanelA.add(anaglyphicLabel);

        anaglyphCheckBox.setText("Anaglyph");
        anaglyphCheckBox.setToolTipText("Anaglyphic view (3D with red-blue glasses)");
        anaglyphCheckBox.setFocusable(false);
        anaglyphCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                anaglyphCheckBoxMouseClicked(evt);
            }
        });
        controlPanelA.add(anaglyphCheckBox);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        graphicModelPanel.add(controlPanelA, gridBagConstraints);

        controlPanelB.setFocusable(false);

        jLabel12.setText("X:");
        controlPanelB.add(jLabel12);

        xLinesComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        xLinesComboBox.setToolTipText("Number of X lines/columns in graphic");
        xLinesComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                xLinesComboBoxActionPerformed(evt);
            }
        });
        controlPanelB.add(xLinesComboBox);

        jLabel13.setText("Y:");
        controlPanelB.add(jLabel13);

        yLinesComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        yLinesComboBox.setToolTipText("<html>Number of Y lines/rows in graphic<br/>(suggest 16 for line drawing, 64 for polygons)</html>");
        yLinesComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                yLinesComboBoxActionPerformed(evt);
            }
        });
        controlPanelB.add(yLinesComboBox);

        polygonCheckBox.setText("Polygons");
        polygonCheckBox.setToolTipText("Polygons instead of lines");
        polygonCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                polygonCheckBoxMouseClicked(evt);
            }
        });
        controlPanelB.add(polygonCheckBox);

        transparencyLabel.setText("| Transp:");
        controlPanelB.add(transparencyLabel);

        transparencyComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        transparencyComboBox.setToolTipText("Polygon Image Transparency");
        controlPanelB.add(transparencyComboBox);

        antialiasingCheckBox.setSelected(true);
        antialiasingCheckBox.setText("Antialiasing");
        antialiasingCheckBox.setToolTipText("Much better appearance, but longer drawing time");
        antialiasingCheckBox.setFocusable(false);
        antialiasingCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                antialiasingCheckBoxMouseClicked(evt);
            }
        });
        controlPanelB.add(antialiasingCheckBox);

        graphicDefaultsButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/edit-clear.png"))); // NOI18N
        graphicDefaultsButton.setText("Defaults");
        graphicDefaultsButton.setToolTipText("Set image default values");
        graphicDefaultsButton.setFocusable(false);
        graphicDefaultsButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                graphicDefaultsButtonMouseClicked(evt);
            }
        });
        controlPanelB.add(graphicDefaultsButton);

        copyButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/edit-copy.png"))); // NOI18N
        copyButton.setText("Copy");
        copyButton.setToolTipText("Copy graphic to clipboard");
        copyButton.setFocusable(false);
        copyButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                copyButtonMouseClicked(evt);
            }
        });
        controlPanelB.add(copyButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        graphicModelPanel.add(controlPanelB, gridBagConstraints);

        mainTabbedPane.addTab("Model", new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/applications-multimedia.png")), graphicModelPanel); // NOI18N

        graphicPanel.setBackground(java.awt.Color.white);
        graphicPanel.setFocusable(false);
        graphicPanel.setLayout(new java.awt.GridBagLayout());

        jScrollPane2.setBackground(java.awt.Color.white);

        helpSlideLabel.setBackground(java.awt.Color.white);
        helpSlideLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jScrollPane2.setViewportView(helpSlideLabel);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        graphicPanel.add(jScrollPane2, gridBagConstraints);

        ghBackButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/go-previous.png"))); // NOI18N
        ghBackButton.setText("Previous");
        ghBackButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                ghBackButtonMouseClicked(evt);
            }
        });
        graphicHelpControls.add(ghBackButton);

        ghForwardButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/go-next.png"))); // NOI18N
        ghForwardButton.setText("Next");
        ghForwardButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                ghForwardButtonMouseClicked(evt);
            }
        });
        graphicHelpControls.add(ghForwardButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        graphicPanel.add(graphicHelpControls, gridBagConstraints);

        mainTabbedPane.addTab("Graphic Help", new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/applications-graphics.png")), graphicPanel); // NOI18N

        helpPanel.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true));
        helpPanel.setFocusable(false);
        helpPanel.setLayout(new java.awt.GridBagLayout());
        mainTabbedPane.addTab("Text Help", new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/system-help.png")), helpPanel); // NOI18N

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        add(mainTabbedPane, gridBagConstraints);

        statusPanel.setFocusable(false);
        statusPanel.setLayout(new java.awt.GridBagLayout());

        statusLabel.setText("Status");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        statusPanel.add(statusLabel, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 0.5;
        statusPanel.add(debug_label, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH;
        gridBagConstraints.weightx = 1.0;
        add(statusPanel, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents

    private void mainTabbedPaneMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mainTabbedPaneMouseClicked
        // TODO add your handling code here:
        processTabClick();
    }//GEN-LAST:event_mainTabbedPaneMouseClicked

    private void ghForwardButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_ghForwardButtonMouseClicked
        // TODO add your handling code here:
        manageHelpSlides(1);
    }//GEN-LAST:event_ghForwardButtonMouseClicked

    private void ghBackButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_ghBackButtonMouseClicked
        // TODO add your handling code here:
        manageHelpSlides(-1);
    }//GEN-LAST:event_ghBackButtonMouseClicked

    private void copyButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_copyButtonMouseClicked
        // TODO add your handling code here:
        mainPanel3d.toClipboard();
    }//GEN-LAST:event_copyButtonMouseClicked

    private void graphicDefaultsButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_graphicDefaultsButtonMouseClicked
        // TODO add your handling code here:
        mainPanel3d.setDefaults(sharedTP);
    }//GEN-LAST:event_graphicDefaultsButtonMouseClicked

    private void antialiasingCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_antialiasingCheckBoxMouseClicked
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_antialiasingCheckBoxMouseClicked

    private void inverseCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_inverseCheckBoxMouseClicked
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_inverseCheckBoxMouseClicked

    private void anaglyphCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_anaglyphCheckBoxMouseClicked
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_anaglyphCheckBoxMouseClicked

    private void sensorCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_sensorCheckBoxMouseClicked
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_sensorCheckBoxMouseClicked

    private void rightCapCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightCapCheckBoxMouseClicked
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_rightCapCheckBoxMouseClicked

    private void cylinderCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_cylinderCheckBoxMouseClicked
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_cylinderCheckBoxMouseClicked

    private void leftCapCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftCapCheckBoxMouseClicked
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_leftCapCheckBoxMouseClicked

    private void buildSpecTableButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_buildSpecTableButtonMouseClicked
        // TODO add your handling code here:
        buildTable(Constants.SPECTABLE,true);
    }//GEN-LAST:event_buildSpecTableButtonMouseClicked

    private void buildVHDataTableButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_buildVHDataTableButtonMouseClicked
        // TODO add your handling code here:
        buildTable(Constants.DATATABLE,true);
    }//GEN-LAST:event_buildVHDataTableButtonMouseClicked

    private void tableCancelButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableCancelButtonMouseClicked
        // TODO add your handling code here:
        cancelTable();
    }//GEN-LAST:event_tableCancelButtonMouseClicked

    private void copyHTMLToClipboardButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_copyHTMLToClipboardButtonMouseClicked
        // TODO add your handling code here:
        copyTableToClipboard(Constants.TABLEHTML);
    }//GEN-LAST:event_copyHTMLToClipboardButtonMouseClicked

    private void decimalPlacesComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_decimalPlacesComboBoxItemStateChanged
        // TODO add your handling code here:
        setModeAndLabels();
    }//GEN-LAST:event_decimalPlacesComboBoxItemStateChanged

    private void singleInputFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_singleInputFieldKeyTyped
        // TODO add your handling code here:
        detectEnterKey(evt);
    }//GEN-LAST:event_singleInputFieldKeyTyped

    private void weightUnitsComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_weightUnitsComboBoxItemStateChanged
        // TODO add your handling code here:
        setModeAndLabels();
    }//GEN-LAST:event_weightUnitsComboBoxItemStateChanged

    private void outputUnitsComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_outputUnitsComboBoxItemStateChanged
        // TODO add your handling code here:
        setModeAndLabels();
    }//GEN-LAST:event_outputUnitsComboBoxItemStateChanged

    private void inputUnitsComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_inputUnitsComboBoxItemStateChanged
        // TODO add your handling code here:
        setModeAndLabels();
    }//GEN-LAST:event_inputUnitsComboBoxItemStateChanged

    private void contentDensityTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_contentDensityTextFieldKeyTyped
        // TODO add your handling code here:
        samc.createIfEnter(evt);
    }//GEN-LAST:event_contentDensityTextFieldKeyTyped

    private void wallDensityTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_wallDensityTextFieldKeyTyped
        // TODO add your handling code here:
        samc.createIfEnter(evt);
    }//GEN-LAST:event_wallDensityTextFieldKeyTyped

    private void wallThicknessTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_wallThicknessTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_wallThicknessTextFieldKeyTyped

    private void sensorZTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_sensorZTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_sensorZTextFieldKeyTyped

    private void sensorYTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_sensorYTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_sensorYTextFieldKeyTyped

    private void sensorXTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_sensorXTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_sensorXTextFieldKeyTyped

    private void sensorOrientationComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_sensorOrientationComboBoxItemStateChanged
        // TODO add your handling code here:
        setModeAndLabels();
    }//GEN-LAST:event_sensorOrientationComboBoxItemStateChanged

    private void tankAngleTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tankAngleTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_tankAngleTextFieldKeyTyped

    private void tankOrientationComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_tankOrientationComboBoxItemStateChanged
        // TODO add your handling code here:
        setModeAndLabels();
    }//GEN-LAST:event_tankOrientationComboBoxItemStateChanged

    private void rightCapComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rightCapComboBoxItemStateChanged
        // TODO add your handling code here:
        setModeAndLabels();
    }//GEN-LAST:event_rightCapComboBoxItemStateChanged

    private void leftCapComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_leftCapComboBoxItemStateChanged
        // TODO add your handling code here:
        setModeAndLabels();
    }//GEN-LAST:event_leftCapComboBoxItemStateChanged

    private void g_rRTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_g_rRTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_g_rRTextFieldKeyTyped

    private void g_rLTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_g_rLTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_g_rLTextFieldKeyTyped

    private void g_RTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_g_RTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_g_RTextFieldKeyTyped

    private void g_LTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_g_LTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_g_LTextFieldKeyTyped

    private void resetButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseClicked
        // TODO add your handling code here:
        setConfigurationDefaults();
    }//GEN-LAST:event_resetButtonMouseClicked

    private void pasteDescButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_pasteDescButtonMouseClicked
        // TODO add your handling code here:
        copyPasteDescription.pasteTankDescriptionFromClipboard();
    }//GEN-LAST:event_pasteDescButtonMouseClicked

    private void copyDescButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_copyDescButtonMouseClicked
        // TODO add your handling code here:
        copyPasteDescription.copyTankDescription();
    }//GEN-LAST:event_copyDescButtonMouseClicked

    private void lineThicknessComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lineThicknessComboBoxActionPerformed
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_lineThicknessComboBoxActionPerformed

    private void xLinesComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_xLinesComboBoxActionPerformed
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_xLinesComboBoxActionPerformed

    private void yLinesComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_yLinesComboBoxActionPerformed
        // TODO add your handling code here:
        readValues();
    }//GEN-LAST:event_yLinesComboBoxActionPerformed

    private void residVolumeTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_residVolumeTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_residVolumeTextFieldKeyTyped

    private void cylinderIntegrationStepsTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_cylinderIntegrationStepsTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_cylinderIntegrationStepsTextFieldKeyTyped

    private void rootFinderEpsilonTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_rootFinderEpsilonTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_rootFinderEpsilonTextFieldKeyTyped

    private void endCapIntegrationStepsTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_endCapIntegrationStepsTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_endCapIntegrationStepsTextFieldKeyTyped

    private void polygonCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_polygonCheckBoxMouseClicked
        // TODO add your handling code here:
        setModeAndLabels();
    }//GEN-LAST:event_polygonCheckBoxMouseClicked

    private void buildHVDataTableButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_buildHVDataTableButtonMouseClicked
        // TODO add your handling code here:
        buildTable(Constants.DATATABLE,false);
    }//GEN-LAST:event_buildHVDataTableButtonMouseClicked

    private void copyTSVToClipboardButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_copyTSVToClipboardButtonMouseClicked
        // TODO add your handling code here:
        copyTableToClipboard(Constants.TABLETSV);
    }//GEN-LAST:event_copyTSVToClipboardButtonMouseClicked

    private void copyPlainToClipboardButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_copyPlainToClipboardButtonMouseClicked
        // TODO add your handling code here:
        copyTableToClipboard(Constants.TABLEPLAIN);
    }//GEN-LAST:event_copyPlainToClipboardButtonMouseClicked

    private void scalingFactorTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_scalingFactorTextFieldKeyTyped
        // TODO add your handling code here:
        setModeIfEnter(evt);
    }//GEN-LAST:event_scalingFactorTextFieldKeyTyped

    // Variables declaration - do not modify//GEN-BEGIN:variables
    protected javax.swing.JLabel LVariableLabel;
    private javax.swing.ButtonGroup NormalInversebuttonGroup;
    protected javax.swing.JLabel RVariableLabel;
    private javax.swing.JPanel SingleResultPanel;
    private javax.swing.JPanel TablePanel;
    protected javax.swing.JCheckBox anaglyphCheckBox;
    protected javax.swing.JLabel anaglyphicLabel;
    protected javax.swing.JCheckBox antialiasingCheckBox;
    private javax.swing.JButton buildHVDataTableButton;
    private javax.swing.JButton buildSpecTableButton;
    private javax.swing.JButton buildVHDataTableButton;
    protected javax.swing.JTextField contentDensityTextField;
    private javax.swing.JPanel controlPanelA;
    private javax.swing.JPanel controlPanelB;
    private javax.swing.JButton copyButton;
    private javax.swing.JButton copyDescButton;
    private javax.swing.JButton copyHTMLToClipboardButton;
    private javax.swing.JButton copyPlainToClipboardButton;
    private javax.swing.JButton copyTSVToClipboardButton;
    protected javax.swing.JCheckBox cylinderCheckBox;
    protected javax.swing.JTextField cylinderIntegrationStepsTextField;
    protected javax.swing.JTable dataTableDisplay;
    protected javax.swing.JLabel debug_label;
    protected javax.swing.JComboBox<Integer> decimalPlacesComboBox;
    protected javax.swing.JTextField endCapIntegrationStepsTextField;
    private javax.swing.JPanel entryPanel;
    private javax.swing.JPanel fillerPanel;
    protected javax.swing.JTextField g_LTextField;
    protected javax.swing.JTextField g_RTextField;
    protected javax.swing.JTextField g_rLTextField;
    protected javax.swing.JTextField g_rRTextField;
    private javax.swing.JButton ghBackButton;
    private javax.swing.JButton ghForwardButton;
    private javax.swing.JButton graphicDefaultsButton;
    private javax.swing.JPanel graphicDisplayPanel;
    private javax.swing.JPanel graphicHelpControls;
    private javax.swing.JPanel graphicModelPanel;
    private javax.swing.JPanel graphicPanel;
    private javax.swing.JLabel heightStepSizeLabel;
    private javax.swing.JPanel helpPanel;
    private javax.swing.JLabel helpSlideLabel;
    private javax.swing.JLabel inputLabel;
    private javax.swing.JPanel inputPanel;
    protected javax.swing.JLabel inputTag;
    protected javax.swing.JComboBox<String> inputUnitsComboBox;
    protected javax.swing.JCheckBox inverseCheckBox;
    protected javax.swing.JLabel jLabel10;
    protected javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    protected javax.swing.JLabel jLabel18;
    protected javax.swing.JLabel jLabel19;
    protected javax.swing.JLabel jLabel20;
    protected javax.swing.JLabel jLabel21;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    protected javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane5;
    protected javax.swing.JLabel lbVariableLabel1;
    protected javax.swing.JLabel lbVariableLabel2;
    protected javax.swing.JCheckBox leftCapCheckBox;
    protected javax.swing.JComboBox leftCapComboBox;
    protected javax.swing.JComboBox<Integer> lineThicknessComboBox;
    private javax.swing.JLabel lineThicknessLabel;
    protected javax.swing.JTabbedPane mainTabbedPane;
    private javax.swing.JPanel modePanel;
    private javax.swing.JLabel outputLabel;
    protected javax.swing.JLabel outputTag;
    protected javax.swing.JComboBox<String> outputUnitsComboBox;
    private javax.swing.JButton pasteDescButton;
    private javax.swing.JCheckBox polygonCheckBox;
    private javax.swing.JButton resetButton;
    protected javax.swing.JLabel residVolumeLabel;
    protected javax.swing.JTextField residVolumeTextField;
    protected javax.swing.JCheckBox rightCapCheckBox;
    protected javax.swing.JComboBox rightCapComboBox;
    protected javax.swing.JTextField rootFinderEpsilonTextField;
    protected javax.swing.JLabel rtVariableLabel1;
    protected javax.swing.JLabel rtVariableLabel2;
    protected javax.swing.JTextField scalingFactorTextField;
    private javax.swing.JLabel scaling_factor_label;
    protected javax.swing.JCheckBox sensorCheckBox;
    protected javax.swing.JComboBox sensorOrientationComboBox;
    protected javax.swing.JLabel sensorPathLabel;
    protected javax.swing.JTextField sensorXTextField;
    protected javax.swing.JTextField sensorYTextField;
    protected javax.swing.JTextField sensorZTextField;
    protected javax.swing.JTextField singleInputField;
    protected javax.swing.JTextField singleOutputField;
    private javax.swing.JLabel statusLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JButton tableCancelButton;
    private javax.swing.JPanel tableControlPanel;
    private javax.swing.JPanel tableDisplayPanel;
    private javax.swing.JPanel tableGenPanel;
    protected javax.swing.JTextField tableHeightStepSizeTextField;
    private javax.swing.JProgressBar tableProgressBar;
    protected javax.swing.JScrollPane tableScrollPane;
    protected javax.swing.JTextField tableTitleTextField;
    private javax.swing.ButtonGroup tableTypeButtonGroup;
    protected javax.swing.JTextField tableVolumeStepSizeTextField;
    protected javax.swing.JLabel tankAngleLabel;
    protected javax.swing.JTextField tankAngleTextField;
    protected javax.swing.JComboBox tankOrientationComboBox;
    protected javax.swing.JComboBox<Integer> transparencyComboBox;
    private javax.swing.JLabel transparencyLabel;
    private javax.swing.JPanel unitsSubPanel;
    private javax.swing.JPanel viewPanel;
    private javax.swing.JLabel volumeStepSizeLabel;
    protected javax.swing.JTextField wallDensityTextField;
    protected javax.swing.JLabel wallThicknessLabel;
    protected javax.swing.JTextField wallThicknessTextField;
    protected javax.swing.JComboBox weightUnitsComboBox;
    protected javax.swing.JLabel xCoordLabel;
    protected javax.swing.JComboBox<Integer> xLinesComboBox;
    protected javax.swing.JLabel yCoordLabel;
    protected javax.swing.JComboBox<Integer> yLinesComboBox;
    protected javax.swing.JLabel zCoordLabel;
    // End of variables declaration//GEN-END:variables
}
