/*
 * TimeSim1.java
 *
 * Created on October 11, 2003, 10:03 PM
 * @author  Barry barry@coilgun.info
 *
 * NOTES ON TABLE MODEL:
 * The "table model" contains all the values in the row and column grid.
 * For this application, the number of columns is sufficient to contain 1 - 10 msec, or 10 columns.
 * And the number of rows can hold 1 microfarad - 1 farad.
 *
 * Scrolling vertically through capacitors is handled automatically by the JScrollPane.
 * Scrolling horizontally through time is done with UI buttons that replace
 * table values and update column headings.
 *
 * To keep a reasonable in-memory table size, we pre-allocate the entire table.
 * This is approximately 11 cols x 98 rows = 1078 items.
 *
 * @see http://java.sun.com/products/jfc/swingdoc-api-1.1.1/javax/swing/JTable.html
 * @see http://java.sun.com/j2se/1.4.1/docs/api/javax/swing/JScrollPane.html
 * @see http://java.sun.com/j2se/1.4.1/docs/api/javax/swing/JScrollBar.html
 */

import javax.swing.*;
import javax.swing.table.*;
import javax.swing.JComponent.*;
import java.awt.Dimension;

public class TimeSim1 extends javax.swing.JApplet {
    public final String sVersion = "v1.2";
    
    /**
     * getAppletInfo is a bean pattern the browser can use to get
     * information about this applet. It can also be used to fill
     * in an About box.
     */
    public String getAppletInfo() {
        return "Name: TimeSim1\r\n"
             + "Author: Barry (barry@coilgun.info)\r\n"
             + "Calculates inductance required in an LC circuit,\r\n"
             + "to result in a desired pulse width for a given capacitor.\r\n";
    }

    /** Initializes the applet TimeSim1 */
    public void init() {
        initComponents();       // create UI controls
        jLabelVersion.setText(sVersion);
        timeButtonGroup.add(jrbZeroCrossing); // group these radio buttons together
        timeButtonGroup.add(jrbHalfPower);    // (is there a way to do it in NetBeans UI?)
        timeButtonGroup.add(jrbFullCycle);
        jrbZeroCrossing.setSelected(true);    // select top radio button
        jLabelIcon.setIcon(createImageIcon("zerocrossing.gif")); // Show image example of timing selected
        String p = jrbZeroCrossing.getText(); // Set title above table to exactly match the button's label
        jLabelTime.setText(p);
        
        cap = Capacitor.initCapacitorList();
        time = initColumnTime(1E-3, 1E-3); // start with 1 msec in leftmost column, increment by 1 msec
        initRowNames();         // put capacitor values into leftmost column
        initColumnNames();      // make column headings
        initInductanceTable();  // fill in entire table with inductor values
        
        // fill in first answer for custom time + cap
        String sAnswer = computeCustom(jTextTime.getText(), jTextCapacitance.getText());
        jLabelAnswer.setText(sAnswer);
    }
    
    /** 
     * Adjust time scale left/right to show prev/next decade of time values
     * Note that columns are always a decade of time: 1-10, or 10-100, or 100-1000
     */
    public void scrollTime(boolean scrollDirection) {
        // obtain tentative new start/end times
        double newStartTime;
	if (scrollDirection == SCROLL_RIGHT) {
	    newStartTime = time[0] * 10;
        }
        else {
            newStartTime = time[0] / 10;
        }
        double newEndTime = newStartTime + newStartTime*TIME_COLUMNS;
        
        // allow scrolling from 1.0 usec - 1 second
        if (scrollDirection == SCROLL_LEFT && newStartTime <= 0.999E-6) return;
        if (scrollDirection == SCROLL_RIGHT && newEndTime >= 9.999) return;
        
        // increment of time from one column to the next
        double incrTime = newStartTime;
        
        // scroll by adding requested amount of time
        time = initColumnTime(newStartTime, incrTime);
        initColumnNames();
        initInductanceTable();  // fill in entire table with inductor values
    }
    
    /** 
     * Initialize the value (seconds) for each column in table
     */
    public double[] initColumnTime(double startTime, double increment) {
        double[] myTime = new double[TIME_COLUMNS];
        for (int tIndex=0; tIndex<TIME_COLUMNS; tIndex++) {
            myTime[tIndex] = startTime + tIndex*increment;
        }
        return myTime;
    }
    
    /**
     * Initialize column headings to show the current times.
     * Called when you scroll/zoom the time scale.
     * All heading numbers have 2 significant figures
     */
    public String[] initColumnNames() {
        // initialize column heading text
        String[] sColumnNames = new String [] {
                "Cap", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
        };
        
        // update the strings
        for (int timeIndex=0; timeIndex<TIME_COLUMNS; timeIndex++) {
            double seconds = time[timeIndex];
            sColumnNames[timeIndex+1] = nearest.toStringEng(seconds, 2, "s");
        }
        
        // Change names of all the columns, using string from above
        TableColumnModel jColModel = jTable.getColumnModel();
        for (int vColIndex=0; vColIndex<sColumnNames.length; vColIndex++) {
            jColModel.getColumn(vColIndex).setHeaderValue( sColumnNames[vColIndex] );
        }
        
        // kluge to update UI (otherwise JTable doesn't repaint column names)
        TableColumn jCol = jTable.getColumn("Cap");
        int width = jCol.getPreferredWidth();
        if (width == 100)
            jCol.setPreferredWidth(101);
        else
            jCol.setPreferredWidth(100);
        
        // return column names for JUnit testing
        return sColumnNames;
    }
    
    /**
     * Initialize all cells in table with inductance value
     */
    public void initInductanceTable() {
        for (int row=0; row<cap.length; row++) {
            for (int tIndex=0; tIndex<TIME_COLUMNS; tIndex++) {
                // compute inductance
                double seconds = time[tIndex];
                double farads = cap[row].getCapacitance();
                double henries = inductor.computeInductance(seconds, farads);
                
                // convert to string, using appropriate milli/micro units
                String sHenries = nearest.toStringEng(henries, 3, "h");
                
                // save inductance in table
                // note row0=first row of data, but col0=row headings
                jTable.setValueAt(sHenries, row, tIndex+1);
            }
        }
    }
    
    /**
     * Initialize row headings by copying capacitor values into column 1.
     */
    public void initRowNames() {
        for (int ii=0; ii<cap.length; ii++) {
            String label = cap[ii].toString();
            jTable.setValueAt(label, ii, 0);
        }
        
        // make leftmost column wide enough for cap labels
        TableColumn jCol = jTable.getColumn("Cap");
        System.out.println("Default column width = " + jCol.getWidth());
        jCol.setMinWidth(60);
        
        // highlight (via selection) every row that's an even multiple of 10
        for (int decade=0; decade<Capacitor.NUMBER_DECADES+1; decade++) {
            int row = decade * Capacitor.CAPACITORS_PER_DECADE;
            jTable.addRowSelectionInterval(row,row);
        }
        
        // scroll down to middle of table (around 2,200 uF for coilguns!)
        /* bwh - removed, it only moves down to 2.7 uF at the most
        JScrollBar jVBar = jScrollPane1.getVerticalScrollBar();
        System.out.println("Vert scroll min/max = " + jVBar.getMinimum() 
                                            + " / " + jVBar.getMaximum() );
        int midpoint = (jVBar.getMaximum() + jVBar.getMinimum())/2;
        jVBar.setValue(midpoint);
         */
    }
    
    /**
     * Helper function to show pictures
     * Returns an ImageIcon, or null if the path was invalid. 
     */
    protected static ImageIcon createImageIcon(String path) {
        java.net.URL imgURL = TimeSim1.class.getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }

    /** This method is called from within the init() method to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
        timeButtonGroup = new javax.swing.ButtonGroup();
        jLabelTitle = new javax.swing.JLabel();
        jLabelAuthor = new javax.swing.JLabel();
        jLabelVersion = new javax.swing.JLabel();
        jLabelTime = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable = new javax.swing.JTable();
        jButtonScrollLeft = new javax.swing.JButton();
        jButtonScrollRight = new javax.swing.JButton();
        jrbZeroCrossing = new javax.swing.JRadioButton();
        jrbHalfPower = new javax.swing.JRadioButton();
        jrbFullCycle = new javax.swing.JRadioButton();
        jLabelTimeButtons = new javax.swing.JLabel();
        jLabelIcon = new javax.swing.JLabel();
        jLabelCustom1 = new javax.swing.JLabel();
        jLabelCustom2 = new javax.swing.JLabel();
        jLabelCapacitancePrompt = new javax.swing.JLabel();
        jLabelTimePrompt = new javax.swing.JLabel();
        jTextCapacitance = new javax.swing.JTextField();
        jTextTime = new javax.swing.JTextField();
        jLabelInductance = new javax.swing.JLabel();
        jLabelAnswer = new javax.swing.JLabel();

        getContentPane().setLayout(null);

        jLabelTitle.setFont(new java.awt.Font("Dialog", 1, 18));
        jLabelTitle.setText("How Much Inductance Do You Need?");
        getContentPane().add(jLabelTitle);
        jLabelTitle.setBounds(90, 0, 323, 24);

        jLabelAuthor.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabelAuthor.setText("barry@coilgun.info");
        jLabelAuthor.setToolTipText("");
        getContentPane().add(jLabelAuthor);
        jLabelAuthor.setBounds(500, 0, 84, 16);

        jLabelVersion.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabelVersion.setText("Version 1.0");
        getContentPane().add(jLabelVersion);
        jLabelVersion.setBounds(500, 20, 62, 16);

        jLabelTime.setFont(new java.awt.Font("Dialog", 1, 18));
        jLabelTime.setForeground(new java.awt.Color(0, 0, 204));
        jLabelTime.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabelTime.setText("Time for one half cycle");
        getContentPane().add(jLabelTime);
        jLabelTime.setBounds(210, 50, 300, 19);

        jScrollPane1.setMinimumSize(new java.awt.Dimension(100, 100));
        jScrollPane1.setPreferredSize(new java.awt.Dimension(600, 250));
        jTable.setBackground(new java.awt.Color(245, 245, 255));
        jTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null}
            },
            new String [] {
                "Cap", "1.0 ms", "2.0 ms", "3.0 ms", "4.0 ms", "5.0 ms", "6.0 ms", "7.0 ms", "8.0 ms", "9.0 ms", "10.0 ms"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, false, false, false, false, false, false, false, false, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jTable.setPreferredScrollableViewportSize(new java.awt.Dimension(500, 400));
        jTable.setRowHeight(18);
        jScrollPane1.setViewportView(jTable);

        getContentPane().add(jScrollPane1);
        jScrollPane1.setBounds(20, 80, 640, 250);

        jButtonScrollLeft.setText("<<<");
        jButtonScrollLeft.setToolTipText("Scroll left");
        jButtonScrollLeft.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButtonScrollLeftMouseClicked(evt);
            }
        });

        getContentPane().add(jButtonScrollLeft);
        jButtonScrollLeft.setBounds(90, 50, 56, 20);

        jButtonScrollRight.setText(">>>");
        jButtonScrollRight.setToolTipText("Scroll right");
        jButtonScrollRight.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButtonScrollRightMouseClicked(evt);
            }
        });

        getContentPane().add(jButtonScrollRight);
        jButtonScrollRight.setBounds(590, 50, 56, 20);

        jrbZeroCrossing.setFont(new java.awt.Font("Dialog", 0, 12));
        jrbZeroCrossing.setMnemonic('Z');
        jrbZeroCrossing.setText("Time for Zero Crossing Pulse");
        jrbZeroCrossing.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                actionZeroCrossing(evt);
            }
        });

        getContentPane().add(jrbZeroCrossing);
        jrbZeroCrossing.setBounds(20, 390, 187, 24);

        jrbHalfPower.setFont(new java.awt.Font("Dialog", 0, 12));
        jrbHalfPower.setMnemonic('H');
        jrbHalfPower.setText("Time for Half Power Pulse");
        jrbHalfPower.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                actionHalfPower(evt);
            }
        });

        getContentPane().add(jrbHalfPower);
        jrbHalfPower.setBounds(20, 370, 168, 24);

        jrbFullCycle.setFont(new java.awt.Font("Dialog", 0, 12));
        jrbFullCycle.setMnemonic('F');
        jrbFullCycle.setText("Time for One Full Cycle");
        jrbFullCycle.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                actionFullCycle(evt);
            }
        });

        getContentPane().add(jrbFullCycle);
        jrbFullCycle.setBounds(20, 410, 152, 24);

        jLabelTimeButtons.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabelTimeButtons.setText("Select a definition of the time period:");
        getContentPane().add(jLabelTimeButtons);
        jLabelTimeButtons.setBounds(20, 350, 198, 16);

        jLabelIcon.setBackground(new java.awt.Color(255, 255, 204));
        jLabelIcon.setForeground(new java.awt.Color(255, 255, 204));
        getContentPane().add(jLabelIcon);
        jLabelIcon.setBounds(230, 350, 125, 110);

        jLabelCustom1.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabelCustom1.setText("Read the inductance in the table above, or");
        getContentPane().add(jLabelCustom1);
        jLabelCustom1.setBounds(420, 350, 240, 16);

        jLabelCustom2.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabelCustom2.setText("or enter your custom values here:");
        getContentPane().add(jLabelCustom2);
        jLabelCustom2.setBounds(420, 370, 230, 16);

        jLabelCapacitancePrompt.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabelCapacitancePrompt.setText("Capacitance (uF):");
        getContentPane().add(jLabelCapacitancePrompt);
        jLabelCapacitancePrompt.setBounds(420, 390, 110, 16);

        jLabelTimePrompt.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabelTimePrompt.setText("Time (usec):");
        getContentPane().add(jLabelTimePrompt);
        jLabelTimePrompt.setBounds(420, 410, 110, 16);

        jTextCapacitance.setText("10000");
        jTextCapacitance.setNextFocusableComponent(jTextTime);
        jTextCapacitance.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                actionCapacitance(evt);
            }
        });

        getContentPane().add(jTextCapacitance);
        jTextCapacitance.setBounds(550, 388, 100, 20);

        jTextTime.setText("1000");
        jTextTime.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                actionTime(evt);
            }
        });

        getContentPane().add(jTextTime);
        jTextTime.setBounds(550, 408, 100, 20);

        jLabelInductance.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabelInductance.setText("Inductance:");
        getContentPane().add(jLabelInductance);
        jLabelInductance.setBounds(420, 430, 110, 16);

        jLabelAnswer.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabelAnswer.setText("(answer)");
        getContentPane().add(jLabelAnswer);
        jLabelAnswer.setBounds(550, 430, 110, 16);

    }//GEN-END:initComponents

    private void actionTime(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_actionTime
        String sAnswer = computeCustom(jTextTime.getText(), jTextCapacitance.getText());
        jLabelAnswer.setText(sAnswer);
    }//GEN-LAST:event_actionTime

    private void actionCapacitance(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_actionCapacitance
        String sAnswer = computeCustom(jTextTime.getText(), jTextCapacitance.getText());
        jLabelAnswer.setText(sAnswer);
    }//GEN-LAST:event_actionCapacitance

    /**
     * After user enters a custom time and capacitor, compute the inductance
     */
    public String computeCustom(String sMicroSeconds, String sMicroFarads) {
        double farads;
        double seconds;
        try {
            farads = Double.parseDouble(sMicroFarads) / 1E6;
            seconds = Double.parseDouble(sMicroSeconds) / 1E6;
        } catch (NumberFormatException doubleTry) {
            return "not a number";
        }
        double henries = inductor.computeInductance(seconds, farads);
        return nearest.toStringEng(henries, 3, "H");
    }
    
    /**
     * When radio button such as "Zero Crossing Pulse Width" is pushed,
     * select its inductance formula and update the GUI.
     */    
    private void actionFullCycle(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_actionFullCycle
        inductor = new Inductor(Inductor.FULL_CYCLE);
        actionTimeButton(evt, "fullcycle.gif");
    }//GEN-LAST:event_actionFullCycle

    private void actionHalfPower(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_actionHalfPower
        inductor = new Inductor(Inductor.HALF_POWER);
        actionTimeButton(evt, "halfpower.gif");
    }//GEN-LAST:event_actionHalfPower

    private void actionZeroCrossing(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_actionZeroCrossing
        inductor = new Inductor(Inductor.ZERO_CROSSING);
        actionTimeButton(evt, "zerocrossing.gif");
    }//GEN-LAST:event_actionZeroCrossing

    // Helper function for radio buttons
    // This does all the common processing to update GUI
    private void actionTimeButton(java.awt.event.ActionEvent evt, String iconName) {
        // Show image example of timing selected
        jLabelIcon.setIcon(createImageIcon(iconName));

        // Set title above table to exactly match the button's label
        String p = evt.getActionCommand();
        jLabelTime.setText(p);
        initInductanceTable();  // fill in entire table with inductor values
        actionCapacitance(evt); // fill in answer for custom entry of cap+time
    }
    
    /**
     * Scroll time scale right/left
     */
    private void jButtonScrollRightMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jButtonScrollRightMouseClicked
        scrollTime( SCROLL_RIGHT );
    }//GEN-LAST:event_jButtonScrollRightMouseClicked

    private void jButtonScrollLeftMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jButtonScrollLeftMouseClicked
        scrollTime( SCROLL_LEFT );
    }//GEN-LAST:event_jButtonScrollLeftMouseClicked
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonScrollLeft;
    private javax.swing.JButton jButtonScrollRight;
    private javax.swing.JLabel jLabelAnswer;
    private javax.swing.JLabel jLabelAuthor;
    private javax.swing.JLabel jLabelCapacitancePrompt;
    private javax.swing.JLabel jLabelCustom1;
    private javax.swing.JLabel jLabelCustom2;
    private javax.swing.JLabel jLabelIcon;
    private javax.swing.JLabel jLabelInductance;
    private javax.swing.JLabel jLabelTime;
    private javax.swing.JLabel jLabelTimeButtons;
    private javax.swing.JLabel jLabelTimePrompt;
    private javax.swing.JLabel jLabelTitle;
    private javax.swing.JLabel jLabelVersion;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable;
    private javax.swing.JTextField jTextCapacitance;
    private javax.swing.JTextField jTextTime;
    private javax.swing.JRadioButton jrbFullCycle;
    private javax.swing.JRadioButton jrbHalfPower;
    private javax.swing.JRadioButton jrbZeroCrossing;
    private javax.swing.ButtonGroup timeButtonGroup;
    // End of variables declaration//GEN-END:variables

    // array of capacitors in the leftmost column of the table
    private Capacitor[] cap;
    
    // helper class for formatting numbers
    private Nearest nearest = new Nearest();
    
    // array of time values (in seconds) in the table
    public double[] time;               // time value (seconds) for each column in table
    public final int TIME_COLUMNS = 10; // number of columns in table that show "time"
    
    private boolean SCROLL_LEFT = false;
    private boolean SCROLL_RIGHT = true;
    
    // input fields for custom values in text entry fields
    double inputCap = 0.01;
    double inputTime = 0.001;
    
    // pointer to class that calculates inductance
    // The object is updated when you select a new time interval (zero-crossing, half power, etc.)
    private Inductor inductor = new Inductor( Inductor.ZERO_CROSSING );
    
}

