/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package main;

import java.awt.Color;
import javax.swing.*;
import javax.swing.filechooser.*;
import generators.*;
import java.awt.Dimension;
import tools.MapFactory;
import java.io.File;

/**
 *
 * @author thelionroars
 */
public class GearGeneratorGUI extends javax.swing.JFrame {
    
    private Config configuration;
    
    private int outerRadius = 256;
    private int innerRadius = 224;
    
    private Color shaded = new Color(200,200,200);
    private Color normal = this.getBackground();
    
    private String outerRadiusTitle = "outerRadius";
    private String outerRadiusDescription = "The radius of the outside of the gear (where the teeth end).";
    
    private String innerRadiusTitle = "innerRadius";
    private String innerRadiusDescription = "The radius of where the teeth begin.";
    
    private String centreRadiusTitle = "centreRadius";
    private String centreRadiusDescription = "The radius of the inside hollow section of the gear. Can be 0. The gear is constructed such that an appropriately matched cylinder generated by the Cylinder Generator will fit perfectly inside this hole. Likewise for discs generated by the Disc Generator and corkscrews generated by the Corkscrew Generator.";
    
    private String outerThicknessTitle = "outerThickness";
    private String outerThicknessDescription = "The thickness of the teeth at the outside perimeter.";
    
    private String innerThicknessTitle = "innerThickness";
    private String innerThicknessDescription = "The thickness of the teeth at the inner radius.";
    
    private String centreThicknessTitle = "centreThickness";
    private String centreThicknessDescription = "The thickness of the gear at the beginning of the center hollow section.";
    
    private String teethTitle = "teeth";
    private String teethDescription = "The number of teeth the gear has.";
    
    private String outerToothLengthRatioTitle = "outerToothLengthRatio";
    private String outerToothLengthRatioDescription = "The ratio of the arc angle of outer tooth to the arc angle of the section that is missing after the tooth at the outer perimeter. Specify -1 to mean an infinite ratio.";
    
    private String innerToothLengthRatioTitle = "innerToothLengthRatio";
    private String innerToothLengthRatioDescription = "The ratio of the arc angle of inner tooth to the arc angle of the section that is missing after the tooth at the inner perimeter. Specify -1 to mean an infinite ratio.";
   
    private String offsetAngleTitle = "offsetAngle";
    private String offsetAngleDescription = "The angle, in degrees, by which to rotate the gear counter-clockwise. When this value is 0, the bottom inside of the first tooth will be touching the X axis.";
    
    /**
     * Creates new form CylinderGeneratorGUI
     */
    public GearGeneratorGUI(Config configuration) {
        initComponents();
        this.configuration = configuration;
        Dimension frameSize = getSize();
        int frameHeight = frameSize.height;
        int frameWidth = frameSize.width;
        if(frameHeight > configuration.getScreenHeight())
        {
            setSize(frameWidth, configuration.getScreenHeight());
        }
    }

    /**
     * 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() {

        options = new javax.swing.ButtonGroup();
        jScrollPane1 = new javax.swing.JScrollPane();
        jScrollPane2 = new javax.swing.JScrollPane();
        jPanel1 = new javax.swing.JPanel();
        iconPanel = new javax.swing.JPanel();
        icon = new javax.swing.JLabel();
        statusPanel = new javax.swing.JPanel();
        generate = new javax.swing.JButton();
        statusScrollPane = new javax.swing.JScrollPane();
        status = new javax.swing.JTextArea();
        descriptionPanel = new javax.swing.JPanel();
        descriptionScrollPane = new javax.swing.JScrollPane();
        description = new javax.swing.JTextArea();
        descriptionTitle = new javax.swing.JLabel();
        subtitlePanel = new javax.swing.JPanel();
        subtitle = new javax.swing.JLabel();
        valuesPanel = new javax.swing.JPanel();
        outerRadiusPanel = new javax.swing.JPanel();
        labOuterRadius = new javax.swing.JLabel();
        inOuterRadius = new javax.swing.JTextField();
        innerThicknessPanel = new javax.swing.JPanel();
        labInnerThickness = new javax.swing.JLabel();
        inInnerThickness = new javax.swing.JTextField();
        centreRadiusPanel = new javax.swing.JPanel();
        labCentreRadius = new javax.swing.JLabel();
        inCentreRadius = new javax.swing.JTextField();
        outerThicknessPanel = new javax.swing.JPanel();
        labOuterThickness = new javax.swing.JLabel();
        inOuterThickness = new javax.swing.JTextField();
        teethPanel = new javax.swing.JPanel();
        labTeeth = new javax.swing.JLabel();
        inTeeth = new javax.swing.JTextField();
        centreThicknessPanel = new javax.swing.JPanel();
        labcentreThickness = new javax.swing.JLabel();
        inCentreThickness = new javax.swing.JTextField();
        innerRadiusPanel = new javax.swing.JPanel();
        labInnerRadius = new javax.swing.JLabel();
        inInnerRadius = new javax.swing.JTextField();
        outerToothLengthRatioPanel = new javax.swing.JPanel();
        inOuterToothLengthRatio = new javax.swing.JTextField();
        labOuterToothLengthRatio = new javax.swing.JLabel();
        innerToothLengthRatioPanel = new javax.swing.JPanel();
        inInnerToothLengthRatio = new javax.swing.JTextField();
        labInnerToothLengthRatio = new javax.swing.JLabel();
        offsetAnglePanel = new javax.swing.JPanel();
        labOffsetAngle = new javax.swing.JLabel();
        inOffsetAngle = new javax.swing.JTextField();

        setTitle("Gear Generator");
        setLocationByPlatform(true);

        icon.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        icon.setIcon(new javax.swing.ImageIcon(getClass().getResource("/main/gear.png"))); // NOI18N
        icon.setFocusable(false);

        javax.swing.GroupLayout iconPanelLayout = new javax.swing.GroupLayout(iconPanel);
        iconPanel.setLayout(iconPanelLayout);
        iconPanelLayout.setHorizontalGroup(
            iconPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(iconPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(icon, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        iconPanelLayout.setVerticalGroup(
            iconPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, iconPanelLayout.createSequentialGroup()
                .addGap(0, 0, Short.MAX_VALUE)
                .addComponent(icon, javax.swing.GroupLayout.PREFERRED_SIZE, 196, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        generate.setText("Generate");
        generate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                generateActionPerformed(evt);
            }
        });

        status.setEditable(false);
        status.setColumns(20);
        status.setRows(5);
        status.setFocusable(false);
        statusScrollPane.setViewportView(status);

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 486, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(generate)
                .addContainerGap())
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(statusScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(generate))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        description.setEditable(false);
        description.setColumns(20);
        description.setLineWrap(true);
        description.setRows(5);
        description.setWrapStyleWord(true);
        description.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        description.setFocusable(false);
        description.setMargin(new java.awt.Insets(5, 5, 5, 5));
        descriptionScrollPane.setViewportView(description);

        descriptionTitle.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

        javax.swing.GroupLayout descriptionPanelLayout = new javax.swing.GroupLayout(descriptionPanel);
        descriptionPanel.setLayout(descriptionPanelLayout);
        descriptionPanelLayout.setHorizontalGroup(
            descriptionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, descriptionPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(descriptionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(descriptionTitle, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(descriptionScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 297, Short.MAX_VALUE))
                .addContainerGap())
        );
        descriptionPanelLayout.setVerticalGroup(
            descriptionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, descriptionPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(descriptionTitle, javax.swing.GroupLayout.PREFERRED_SIZE, 43, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(descriptionScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 258, Short.MAX_VALUE)
                .addContainerGap())
        );

        subtitle.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        subtitle.setText("Generates a gear as a .map file to be opened in GtkRadiant.");

        javax.swing.GroupLayout subtitlePanelLayout = new javax.swing.GroupLayout(subtitlePanel);
        subtitlePanel.setLayout(subtitlePanelLayout);
        subtitlePanelLayout.setHorizontalGroup(
            subtitlePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(subtitlePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(subtitle, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        subtitlePanelLayout.setVerticalGroup(
            subtitlePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(subtitle, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        outerRadiusPanel.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                outerRadiusPanelFocusGained(evt);
            }
        });

        labOuterRadius.setLabelFor(inOuterRadius);
        labOuterRadius.setText("outerRadius:");

        inOuterRadius.setText("256");
        inOuterRadius.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inOuterRadiusActionPerformed(evt);
            }
        });
        inOuterRadius.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inOuterRadiusFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inOuterRadiusFocusLost(evt);
            }
        });

        javax.swing.GroupLayout outerRadiusPanelLayout = new javax.swing.GroupLayout(outerRadiusPanel);
        outerRadiusPanel.setLayout(outerRadiusPanelLayout);
        outerRadiusPanelLayout.setHorizontalGroup(
            outerRadiusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(outerRadiusPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(labOuterRadius)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(inOuterRadius, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        outerRadiusPanelLayout.setVerticalGroup(
            outerRadiusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, outerRadiusPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(outerRadiusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labOuterRadius)
                    .addComponent(inOuterRadius, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        labInnerThickness.setLabelFor(inInnerThickness);
        labInnerThickness.setText("innerThickness:");

        inInnerThickness.setText("64");
        inInnerThickness.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inInnerThicknessActionPerformed(evt);
            }
        });
        inInnerThickness.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inInnerThicknessFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inInnerThicknessFocusLost(evt);
            }
        });

        javax.swing.GroupLayout innerThicknessPanelLayout = new javax.swing.GroupLayout(innerThicknessPanel);
        innerThicknessPanel.setLayout(innerThicknessPanelLayout);
        innerThicknessPanelLayout.setHorizontalGroup(
            innerThicknessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(innerThicknessPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(labInnerThickness)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(inInnerThickness, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        innerThicknessPanelLayout.setVerticalGroup(
            innerThicknessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, innerThicknessPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(innerThicknessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labInnerThickness)
                    .addComponent(inInnerThickness, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        labCentreRadius.setLabelFor(inCentreRadius);
        labCentreRadius.setText("centreRadius:");

        inCentreRadius.setText("168");
        inCentreRadius.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inCentreRadiusActionPerformed(evt);
            }
        });
        inCentreRadius.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inCentreRadiusFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inCentreRadiusFocusLost(evt);
            }
        });

        javax.swing.GroupLayout centreRadiusPanelLayout = new javax.swing.GroupLayout(centreRadiusPanel);
        centreRadiusPanel.setLayout(centreRadiusPanelLayout);
        centreRadiusPanelLayout.setHorizontalGroup(
            centreRadiusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(centreRadiusPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(labCentreRadius)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(inCentreRadius, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        centreRadiusPanelLayout.setVerticalGroup(
            centreRadiusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, centreRadiusPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(centreRadiusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labCentreRadius)
                    .addComponent(inCentreRadius, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        labOuterThickness.setLabelFor(inOuterThickness);
        labOuterThickness.setText("outerThickness:");

        inOuterThickness.setText("48");
        inOuterThickness.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inOuterThicknessActionPerformed(evt);
            }
        });
        inOuterThickness.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inOuterThicknessFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inOuterThicknessFocusLost(evt);
            }
        });

        javax.swing.GroupLayout outerThicknessPanelLayout = new javax.swing.GroupLayout(outerThicknessPanel);
        outerThicknessPanel.setLayout(outerThicknessPanelLayout);
        outerThicknessPanelLayout.setHorizontalGroup(
            outerThicknessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(outerThicknessPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(labOuterThickness)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(inOuterThickness, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        outerThicknessPanelLayout.setVerticalGroup(
            outerThicknessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(outerThicknessPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(outerThicknessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labOuterThickness)
                    .addComponent(inOuterThickness, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        labTeeth.setLabelFor(inInnerThickness);
        labTeeth.setText("teeth:");

        inTeeth.setText("24");
        inTeeth.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inTeethActionPerformed(evt);
            }
        });
        inTeeth.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inTeethFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inTeethFocusLost(evt);
            }
        });

        javax.swing.GroupLayout teethPanelLayout = new javax.swing.GroupLayout(teethPanel);
        teethPanel.setLayout(teethPanelLayout);
        teethPanelLayout.setHorizontalGroup(
            teethPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(teethPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(labTeeth)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(inTeeth, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        teethPanelLayout.setVerticalGroup(
            teethPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, teethPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(teethPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labTeeth)
                    .addComponent(inTeeth, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        labcentreThickness.setLabelFor(inInnerThickness);
        labcentreThickness.setText("centreThickness:");

        inCentreThickness.setText("32");
        inCentreThickness.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inCentreThicknessActionPerformed(evt);
            }
        });
        inCentreThickness.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inCentreThicknessFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inCentreThicknessFocusLost(evt);
            }
        });

        javax.swing.GroupLayout centreThicknessPanelLayout = new javax.swing.GroupLayout(centreThicknessPanel);
        centreThicknessPanel.setLayout(centreThicknessPanelLayout);
        centreThicknessPanelLayout.setHorizontalGroup(
            centreThicknessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(centreThicknessPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(labcentreThickness)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(inCentreThickness, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        centreThicknessPanelLayout.setVerticalGroup(
            centreThicknessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, centreThicknessPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(centreThicknessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labcentreThickness)
                    .addComponent(inCentreThickness, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        innerRadiusPanel.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                innerRadiusPanelFocusGained(evt);
            }
        });

        labInnerRadius.setLabelFor(inOuterRadius);
        labInnerRadius.setText("innerRadius:");

        inInnerRadius.setText("224");
        inInnerRadius.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inInnerRadiusActionPerformed(evt);
            }
        });
        inInnerRadius.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inInnerRadiusFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inInnerRadiusFocusLost(evt);
            }
        });

        javax.swing.GroupLayout innerRadiusPanelLayout = new javax.swing.GroupLayout(innerRadiusPanel);
        innerRadiusPanel.setLayout(innerRadiusPanelLayout);
        innerRadiusPanelLayout.setHorizontalGroup(
            innerRadiusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(innerRadiusPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(labInnerRadius)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(inInnerRadius, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        innerRadiusPanelLayout.setVerticalGroup(
            innerRadiusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, innerRadiusPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(innerRadiusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labInnerRadius)
                    .addComponent(inInnerRadius, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        inOuterToothLengthRatio.setText("0.55");
        inOuterToothLengthRatio.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inOuterToothLengthRatioActionPerformed(evt);
            }
        });
        inOuterToothLengthRatio.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inOuterToothLengthRatioFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inOuterToothLengthRatioFocusLost(evt);
            }
        });

        labOuterToothLengthRatio.setLabelFor(inInnerThickness);
        labOuterToothLengthRatio.setText("outerToothLengthRatio:");

        javax.swing.GroupLayout outerToothLengthRatioPanelLayout = new javax.swing.GroupLayout(outerToothLengthRatioPanel);
        outerToothLengthRatioPanel.setLayout(outerToothLengthRatioPanelLayout);
        outerToothLengthRatioPanelLayout.setHorizontalGroup(
            outerToothLengthRatioPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, outerToothLengthRatioPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(labOuterToothLengthRatio)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(inOuterToothLengthRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        outerToothLengthRatioPanelLayout.setVerticalGroup(
            outerToothLengthRatioPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, outerToothLengthRatioPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(outerToothLengthRatioPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(inOuterToothLengthRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(labOuterToothLengthRatio))
                .addContainerGap())
        );

        inInnerToothLengthRatio.setText("1.6");
        inInnerToothLengthRatio.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inInnerToothLengthRatioActionPerformed(evt);
            }
        });
        inInnerToothLengthRatio.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inInnerToothLengthRatioFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inInnerToothLengthRatioFocusLost(evt);
            }
        });

        labInnerToothLengthRatio.setLabelFor(inInnerThickness);
        labInnerToothLengthRatio.setText("innerToothLengthRatio:");

        javax.swing.GroupLayout innerToothLengthRatioPanelLayout = new javax.swing.GroupLayout(innerToothLengthRatioPanel);
        innerToothLengthRatioPanel.setLayout(innerToothLengthRatioPanelLayout);
        innerToothLengthRatioPanelLayout.setHorizontalGroup(
            innerToothLengthRatioPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, innerToothLengthRatioPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(labInnerToothLengthRatio)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(inInnerToothLengthRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        innerToothLengthRatioPanelLayout.setVerticalGroup(
            innerToothLengthRatioPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(innerToothLengthRatioPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(innerToothLengthRatioPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(inInnerToothLengthRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(labInnerToothLengthRatio))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        labOffsetAngle.setLabelFor(inInnerThickness);
        labOffsetAngle.setText("offsetAngle:");

        inOffsetAngle.setText("0.0");
        inOffsetAngle.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                inOffsetAngleActionPerformed(evt);
            }
        });
        inOffsetAngle.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                inOffsetAngleFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                inOffsetAngleFocusLost(evt);
            }
        });

        javax.swing.GroupLayout offsetAnglePanelLayout = new javax.swing.GroupLayout(offsetAnglePanel);
        offsetAnglePanel.setLayout(offsetAnglePanelLayout);
        offsetAnglePanelLayout.setHorizontalGroup(
            offsetAnglePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(offsetAnglePanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(labOffsetAngle)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(inOffsetAngle, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        offsetAnglePanelLayout.setVerticalGroup(
            offsetAnglePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, offsetAnglePanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(offsetAnglePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labOffsetAngle)
                    .addComponent(inOffsetAngle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        javax.swing.GroupLayout valuesPanelLayout = new javax.swing.GroupLayout(valuesPanel);
        valuesPanel.setLayout(valuesPanelLayout);
        valuesPanelLayout.setHorizontalGroup(
            valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(valuesPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(valuesPanelLayout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(innerRadiusPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(outerRadiusPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(innerThicknessPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(outerThicknessPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(centreRadiusPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(centreThicknessPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(teethPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(outerToothLengthRatioPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                    .addComponent(innerToothLengthRatioPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(offsetAnglePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );
        valuesPanelLayout.setVerticalGroup(
            valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(valuesPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(outerRadiusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(innerRadiusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(centreRadiusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(outerThicknessPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(innerThicknessPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(centreThicknessPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(teethPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(outerToothLengthRatioPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(innerToothLengthRatioPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(offsetAnglePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(subtitlePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(statusPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                        .addComponent(valuesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(descriptionPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                                .addComponent(iconPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(40, 40, 40)))))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGap(28, 28, 28)
                .addComponent(subtitlePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(descriptionPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(iconPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(43, 43, 43)
                        .addComponent(valuesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE)
                .addComponent(statusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        jScrollPane2.setViewportView(jPanel1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane2)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane2)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void inOuterRadiusFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inOuterRadiusFocusGained
        
        outerRadiusPanel.setBackground(shaded);
        descriptionTitle.setText(outerRadiusTitle);
        description.setText(outerRadiusDescription);
    }//GEN-LAST:event_inOuterRadiusFocusGained

    private void inOuterRadiusFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inOuterRadiusFocusLost
        
        checkGenerateOK();
    }//GEN-LAST:event_inOuterRadiusFocusLost

    private void outerRadiusPanelFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_outerRadiusPanelFocusGained

    }//GEN-LAST:event_outerRadiusPanelFocusGained

    private void inInnerThicknessFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inInnerThicknessFocusGained
        innerThicknessPanel.setBackground(shaded);
        descriptionTitle.setText(innerThicknessTitle);
        description.setText(innerThicknessDescription);
    }//GEN-LAST:event_inInnerThicknessFocusGained

    private void inInnerThicknessFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inInnerThicknessFocusLost
        
        checkGenerateOK();
    }//GEN-LAST:event_inInnerThicknessFocusLost

    private void inCentreRadiusFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inCentreRadiusFocusGained
        
        centreRadiusPanel.setBackground(shaded);
        descriptionTitle.setText(centreRadiusTitle);
        description.setText(centreRadiusDescription);
    }//GEN-LAST:event_inCentreRadiusFocusGained

    private void inCentreRadiusFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inCentreRadiusFocusLost
        
        checkGenerateOK();
    }//GEN-LAST:event_inCentreRadiusFocusLost

    private void generateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_generateActionPerformed
        
        generate.setEnabled(false); // Prevents double saves
        
        String[] args = {inOuterRadius.getText(), inInnerRadius.getText(), inCentreRadius.getText(), inOuterThickness.getText(), inInnerThickness.getText(), inCentreThickness.getText(), inTeeth.getText(), inOuterToothLengthRatio.getText(), inInnerToothLengthRatio.getText(), inOffsetAngle.getText() };
        status.setText("Generating gear...");
        GearGenerator.main(args);
        
        // Save the resultant map file (or cancel)
        status.setText("Generated - select save file name and location");
        JFileChooser chooser = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Quake Map File (.map)", "map");
        chooser.setFileFilter(filter);
        
        File saveFile = null;
        String filename = null;
        boolean save = true;
        
        while(save)
        {
            if((configuration.getWorkingDirectory() != null) && (configuration.getWorkingDirectory().isDirectory()))
                    chooser.setCurrentDirectory(configuration.getWorkingDirectory());
            int returnValue = chooser.showSaveDialog(this);
            if(returnValue == JFileChooser.CANCEL_OPTION || returnValue == JFileChooser.ERROR_OPTION) 
            {
                save = false;
            }
            else
            {
                
                saveFile = chooser.getSelectedFile();
                filename = saveFile.getAbsolutePath();
                if(!(filename.endsWith(".map")))
                    filename += ".map";
                saveFile = new File(filename);
                if(saveFile.exists())
                {
                    Object[] buttons = { "Cancel", "No", "Yes" };
                    int response = JOptionPane.showOptionDialog(this, "Overwrite " + filename + " ?", "Confirm Overwrite", JOptionPane.WARNING_MESSAGE, 0, null, buttons, buttons[1]);
                    
                    if(response == 1)
                        continue;
                    if(response == 0)
                        save = false;
                }
            }
            if(save)
            {
                status.setText("Saving...");
                MapFactory.saveText(filename);
                statusPanel.setBackground(Color.green);
                status.setText("Save successful\n" + filename);
                configuration.setWorkingDirectory(saveFile.getParentFile());
                save = false;
            }
            else
                status.setText("Save Cancelled");
        }
            
    }//GEN-LAST:event_generateActionPerformed

    private void inInnerRadiusFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inInnerRadiusFocusGained
        
        innerRadiusPanel.setBackground(shaded);
        descriptionTitle.setText(innerRadiusTitle);
        description.setText(innerRadiusDescription);
    }//GEN-LAST:event_inInnerRadiusFocusGained

    private void inInnerRadiusFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inInnerRadiusFocusLost
        checkGenerateOK();
    }//GEN-LAST:event_inInnerRadiusFocusLost

    private void innerRadiusPanelFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_innerRadiusPanelFocusGained
        // TODO add your handling code here:
    }//GEN-LAST:event_innerRadiusPanelFocusGained

    private void inOuterThicknessFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inOuterThicknessFocusLost

        checkGenerateOK();
    }//GEN-LAST:event_inOuterThicknessFocusLost

    private void inOuterThicknessFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inOuterThicknessFocusGained

        outerThicknessPanel.setBackground(shaded);
        descriptionTitle.setText(outerThicknessTitle);
        description.setText(outerThicknessDescription);
    }//GEN-LAST:event_inOuterThicknessFocusGained

    private void inOffsetAngleFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inOffsetAngleFocusGained
        
        offsetAnglePanel.setBackground(shaded);
        descriptionTitle.setText(offsetAngleTitle);
        description.setText(offsetAngleDescription);
    }//GEN-LAST:event_inOffsetAngleFocusGained

    private void inOffsetAngleFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inOffsetAngleFocusLost
        
        checkGenerateOK();
    }//GEN-LAST:event_inOffsetAngleFocusLost

    private void inOffsetAngleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inOffsetAngleActionPerformed
        
        checkGenerateOK();
    }//GEN-LAST:event_inOffsetAngleActionPerformed

    private void inInnerThicknessActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inInnerThicknessActionPerformed
        
        checkGenerateOK();
    }//GEN-LAST:event_inInnerThicknessActionPerformed

    private void inOuterThicknessActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inOuterThicknessActionPerformed
        
        checkGenerateOK();
    }//GEN-LAST:event_inOuterThicknessActionPerformed

    private void inCentreRadiusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inCentreRadiusActionPerformed
        
        checkGenerateOK();
    }//GEN-LAST:event_inCentreRadiusActionPerformed

    private void inInnerRadiusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inInnerRadiusActionPerformed
        
        checkGenerateOK();
    }//GEN-LAST:event_inInnerRadiusActionPerformed

    private void inOuterRadiusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inOuterRadiusActionPerformed
        
        checkGenerateOK();
    }//GEN-LAST:event_inOuterRadiusActionPerformed

    private void inCentreThicknessActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inCentreThicknessActionPerformed
       
        checkGenerateOK();
    }//GEN-LAST:event_inCentreThicknessActionPerformed

    private void inCentreThicknessFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inCentreThicknessFocusGained
        
        centreThicknessPanel.setBackground(shaded);
        descriptionTitle.setText(centreThicknessTitle);
        description.setText(centreThicknessDescription);
    }//GEN-LAST:event_inCentreThicknessFocusGained

    private void inCentreThicknessFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inCentreThicknessFocusLost
        
        checkGenerateOK();
    }//GEN-LAST:event_inCentreThicknessFocusLost

    private void inTeethActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inTeethActionPerformed
        
        checkGenerateOK();
    }//GEN-LAST:event_inTeethActionPerformed

    private void inTeethFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inTeethFocusGained
        
        teethPanel.setBackground(shaded);
        descriptionTitle.setText(teethTitle);
        description.setText(teethDescription);
    }//GEN-LAST:event_inTeethFocusGained

    private void inTeethFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inTeethFocusLost
        
        checkGenerateOK();
    }//GEN-LAST:event_inTeethFocusLost

    private void inOuterToothLengthRatioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inOuterToothLengthRatioActionPerformed
        
        checkGenerateOK();
    }//GEN-LAST:event_inOuterToothLengthRatioActionPerformed

    private void inOuterToothLengthRatioFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inOuterToothLengthRatioFocusGained
        
        outerToothLengthRatioPanel.setBackground(shaded);
        descriptionTitle.setText(outerToothLengthRatioTitle);
        description.setText(outerToothLengthRatioDescription);
    }//GEN-LAST:event_inOuterToothLengthRatioFocusGained

    private void inOuterToothLengthRatioFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inOuterToothLengthRatioFocusLost
        
        checkGenerateOK();
    }//GEN-LAST:event_inOuterToothLengthRatioFocusLost

    private void inInnerToothLengthRatioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_inInnerToothLengthRatioActionPerformed
        
        checkGenerateOK();
    }//GEN-LAST:event_inInnerToothLengthRatioActionPerformed

    private void inInnerToothLengthRatioFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inInnerToothLengthRatioFocusGained
        
        innerToothLengthRatioPanel.setBackground(shaded);
        descriptionTitle.setText(innerToothLengthRatioTitle);
        description.setText(innerToothLengthRatioDescription);
    }//GEN-LAST:event_inInnerToothLengthRatioFocusGained

    private void inInnerToothLengthRatioFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inInnerToothLengthRatioFocusLost
        
        checkGenerateOK();
    }//GEN-LAST:event_inInnerToothLengthRatioFocusLost

    /**
     * Validation for values and options. 
     * 
     * Will disable unneeded values for a given option, and ensure needed values are enabled.
     * For any failed check, will highlight the panel in red and disable the submit button. A message will be 
     * added to the status TextArea and the status panel will be highlighted in Yellow
     */
    private void checkGenerateOK()
    {
        boolean generateOK = true;
        statusPanel.setBackground(normal);
        status.setText("");
        String statusText = ""; // used to build error msg list
        
        // check inOuterRadius
        try
        {
            int temp = Integer.parseInt(inOuterRadius.getText());

            if(temp <= 1)
                throw new Exception("outerRadius must be positive");
            if(temp < innerRadius)
                throw new Exception("outerRadius must be greater than or equal to innerRadius");
            
            outerRadius = temp;
            outerRadiusPanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for outerRadius\n";
            else
                statusText += ex.getMessage() + "\n";
            outerRadiusPanel.setBackground(Color.red);
        }
        
        // check innerRadius
        try
        {
            int temp = Integer.parseInt(inInnerRadius.getText());
            
            if(temp < 0)
                throw new Exception("innerRadius cannot be negative");
            if(temp > outerRadius)
                throw new Exception("innerRadius must be less than or equal to outerRadius");
            
            innerRadius = temp;
            innerRadiusPanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for outerRadius\n";
            else
                statusText += ex.getMessage() + "\n";
            innerRadiusPanel.setBackground(Color.red);
        }
        
        //check inCentreRadius ok
        try
        {
            int temp = Integer.parseInt(inCentreRadius.getText());
            
            if(temp < 0)
                throw new Exception("centreRadius cannot be negative");
            
            centreRadiusPanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for centreRadius\n";
            else
                statusText += ex.getMessage() + "\n";
            centreRadiusPanel.setBackground(Color.red);
        }
        
        //check inOuterThickness ok
        try
        {
            int temp = Integer.parseInt(inOuterThickness.getText());
            
            if(temp < 0)
                throw new Exception("outerThickness cannot be negative");
            
            outerThicknessPanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for outerThickness\n";
            else
                statusText += ex.getMessage() + "\n";
            outerThicknessPanel.setBackground(Color.red);

        }
        
        // check inInnerThickness ok
        try
        {
            int temp = Integer.parseInt(inInnerThickness.getText());

            if(temp < 0)
                throw new Exception("innerThickness cannot be negative");

            innerThicknessPanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            statusPanel.setBackground(Color.yellow);
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for innerThickness\n";
            else
                statusText += ex.getMessage() + "\n";
            
            innerThicknessPanel.setBackground(Color.red);
        }
        
        // check inCentreThickness ok
        try
        {
            int temp = Integer.parseInt(inCentreThickness.getText());
            
            if(temp < 0)
                throw new Exception("centreThickness cannot be negative");
            
            centreThicknessPanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            statusPanel.setBackground(Color.yellow);
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for centreThickness\n";
            else
                statusText += ex.getMessage() + "\n";
            
            centreThicknessPanel.setBackground(Color.red);
        }
        
        // check inTeeth ok
        try
        {
            int temp = Integer.parseInt(inTeeth.getText());
            
            if(temp < 0)
                throw new Exception("teeth cannot be negative");
            
             teethPanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            statusPanel.setBackground(Color.yellow);
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for teeth\n";
            else
                statusText += ex.getMessage() + "\n";
            
            teethPanel.setBackground(Color.red);
        }
        
        // check inOuterToothLengthRatio ok
        try
        {
            double temp = Double.parseDouble(inOuterToothLengthRatio.getText());
            
             outerToothLengthRatioPanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            statusPanel.setBackground(Color.yellow);
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for innerToothLengthRatio\n";
            else
                statusText += ex.getMessage() + "\n";
            
            outerToothLengthRatioPanel.setBackground(Color.red);
        }
        
        // check inInnerToothLengthRatio ok
        try
        {
            double temp = Double.parseDouble(inInnerToothLengthRatio.getText());
            
             innerToothLengthRatioPanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            statusPanel.setBackground(Color.yellow);
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for innerToothLengthRatio\n";
            else
                statusText += ex.getMessage() + "\n";
            
            innerToothLengthRatioPanel.setBackground(Color.red);
        }
        
        
        // check inOffsetAngle ok
        try
        {
            double temp = Double.parseDouble(inOffsetAngle.getText());
            
            if(temp < 0)
                throw new Exception("Please enter a positive number");
            
            offsetAnglePanel.setBackground(normal);
        }
        catch(Exception ex)
        {
            generateOK = false;
            if(ex instanceof NumberFormatException)
                statusText += "Please enter a number for the offsetAngle\n";
            else
                statusText += ex.getMessage() + "\n";
            offsetAnglePanel.setBackground(Color.red);
        }
        
        if(generateOK)
            generate.setEnabled(true);
        else
        {
            generate.setEnabled(false);
            statusPanel.setBackground(Color.yellow);
            status.setText(statusText);
        }
    }
    
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(GearGeneratorGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(GearGeneratorGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(GearGeneratorGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(GearGeneratorGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new GearGeneratorGUI(new Config()).setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel centreRadiusPanel;
    private javax.swing.JPanel centreThicknessPanel;
    private javax.swing.JTextArea description;
    private javax.swing.JPanel descriptionPanel;
    private javax.swing.JScrollPane descriptionScrollPane;
    private javax.swing.JLabel descriptionTitle;
    private javax.swing.JButton generate;
    private javax.swing.JLabel icon;
    private javax.swing.JPanel iconPanel;
    private javax.swing.JTextField inCentreRadius;
    private javax.swing.JTextField inCentreThickness;
    private javax.swing.JTextField inInnerRadius;
    private javax.swing.JTextField inInnerThickness;
    private javax.swing.JTextField inInnerToothLengthRatio;
    private javax.swing.JTextField inOffsetAngle;
    private javax.swing.JTextField inOuterRadius;
    private javax.swing.JTextField inOuterThickness;
    private javax.swing.JTextField inOuterToothLengthRatio;
    private javax.swing.JTextField inTeeth;
    private javax.swing.JPanel innerRadiusPanel;
    private javax.swing.JPanel innerThicknessPanel;
    private javax.swing.JPanel innerToothLengthRatioPanel;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel labCentreRadius;
    private javax.swing.JLabel labInnerRadius;
    private javax.swing.JLabel labInnerThickness;
    private javax.swing.JLabel labInnerToothLengthRatio;
    private javax.swing.JLabel labOffsetAngle;
    private javax.swing.JLabel labOuterRadius;
    private javax.swing.JLabel labOuterThickness;
    private javax.swing.JLabel labOuterToothLengthRatio;
    private javax.swing.JLabel labTeeth;
    private javax.swing.JLabel labcentreThickness;
    private javax.swing.JPanel offsetAnglePanel;
    private javax.swing.ButtonGroup options;
    private javax.swing.JPanel outerRadiusPanel;
    private javax.swing.JPanel outerThicknessPanel;
    private javax.swing.JPanel outerToothLengthRatioPanel;
    private javax.swing.JTextArea status;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JScrollPane statusScrollPane;
    private javax.swing.JLabel subtitle;
    private javax.swing.JPanel subtitlePanel;
    private javax.swing.JPanel teethPanel;
    private javax.swing.JPanel valuesPanel;
    // End of variables declaration//GEN-END:variables
}
