/*
 * AnimationSettingsPanel.java
 *
 * Created on December 25, 2000, 12:54 PM
 */

package pharynx;
import javax.swing.*;
import java.text.*;

/**
 *
 * @author  leon@eatworms.swmed.edu
 * @version 0.1
 */
public class AnimationSettingsPanel extends javax.swing.JPanel {
    private SimOptions options = new SimOptions();
    private SimOptions.Updater updater;

    /** Creates new form AnimationSettingsPanel
     *
     * This constructor for the sake of the forte GUI editor
     */
    public AnimationSettingsPanel() {
        this.updater = updater;
        initComponents();
        readOptions();
    }

    /** Creates new form AnimationSettingsPanel */
    public AnimationSettingsPanel(SimOptions.Updater updater) {
        this.updater = updater;
        initComponents();
        readOptions();
    }

    private boolean readOptions() {
        try {
            options.start = Double.parseDouble(startAnimationTextField.getText());
            double smoothness = Double.parseDouble(smoothnessTextField.getText());
            options.frame = (int) Math.round(200 / smoothness);
            double speed = Double.parseDouble(speedTextField.getText());
            options.dt = options.frame / speed;
            options.antialias = antiAliasCheckBox.isSelected();
            if (!smoothnessChanging) {
                smoothnessChanging = true;
                smoothnessSlider.setValue(decodeSmoothness(null));
                smoothnessChanging = false;
            }
            if (speedChanging) {
                speedChanging = true;
                speedSlider.setValue(decodeSpeed(null));
                speedChanging = false;
            }
            return true;
        } catch(NumberFormatException e) {
            errorPopup(e);
            return false;
        }
    }
    
    private void update() {
        if (readOptions() && (null != updater))
            updater.update(null);
    }
    
    /**
     * Get the user's animation settings
     *
     * @return          new SimOptions with Animation settings filled in
     */
    public SimOptions getOptions() {
        if (!readOptions())
            throw new InvalidSettingsException();
        return(new SimOptions(options));
    }
    
    /**
     * Get the user's animation settings
     *
     * @param options   Current option settings or null
     * @return          new SimOptions with Animation settings filled in
     */
    public SimOptions getOptions(SimOptions options) {
        if (!readOptions())
            throw new InvalidSettingsException();
        SimOptions o = new SimOptions(options);
        o.start = this.options.start;
        o.dt = this.options.dt;
        o.frame = this.options.frame;
        o.antialias = this.options.antialias;
        return(o);
    }
    
    /** 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 FormEditor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
        speedLabel = new javax.swing.JLabel();
        smoothnessLabel = new javax.swing.JLabel();
        antiAliasCheckBox = new javax.swing.JCheckBox();
        speedSlider = new javax.swing.JSlider();
        smoothnessSlider = new javax.swing.JSlider();
        startAnimationLabel = new javax.swing.JLabel();
        speedTextField = new javax.swing.JTextField();
        smoothnessTextField = new javax.swing.JTextField();
        startAnimationTextField = new javax.swing.JTextField();
        setLayout(new java.awt.GridLayout(3, 3));
        setPreferredSize(new java.awt.Dimension(400, 81));
        
        speedLabel.setText("Slowdown");
        speedLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        
        add(speedLabel);
        
        
        smoothnessLabel.setText("Smoothness");
        smoothnessLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        
        add(smoothnessLabel);
        
        
        antiAliasCheckBox.setSelected(true);
        antiAliasCheckBox.setText("Antialias");
        antiAliasCheckBox.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        antiAliasCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                antiAliasCheckBoxStateChanged(evt);
            }
        }
        );
        
        add(antiAliasCheckBox);
        
        
        speedSlider.setPaintTicks(true);
        speedSlider.setMajorTickSpacing(20);
        speedSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                speedSliderStateChanged(evt);
            }
        }
        );
        
        add(speedSlider);
        
        
        smoothnessSlider.setPaintTicks(true);
        smoothnessSlider.setMajorTickSpacing(20);
        smoothnessSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                smoothnessSliderStateChanged(evt);
            }
        }
        );
        
        add(smoothnessSlider);
        
        
        startAnimationLabel.setText("Start Time");
        startAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        
        add(startAnimationLabel);
        
        
        speedTextField.setText("100");
        speedTextField.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        speedTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                speedTextFieldActionPerformed(evt);
            }
        }
        );
        
        add(speedTextField);
        
        
        smoothnessTextField.setText("1.0");
        smoothnessTextField.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        smoothnessTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                smoothnessTextFieldActionPerformed(evt);
            }
        }
        );
        
        add(smoothnessTextField);
        
        
        startAnimationTextField.setText("0");
        startAnimationTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startAnimationTextFieldActionPerformed(evt);
            }
        }
        );
        
        add(startAnimationTextField);
        
    }//GEN-END:initComponents

  private void antiAliasCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_antiAliasCheckBoxStateChanged
        update();
  }//GEN-LAST:event_antiAliasCheckBoxStateChanged

  private void startAnimationTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startAnimationTextFieldActionPerformed
        update();
  }//GEN-LAST:event_startAnimationTextFieldActionPerformed

    private boolean smoothnessChanging = false;
    private boolean speedChanging = false;
  
  private void smoothnessTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_smoothnessTextFieldActionPerformed
        if (smoothnessChanging) return;
        smoothnessChanging = true;
        smoothnessSlider.setValue(decodeSmoothness(evt));
        update();
        smoothnessChanging = false;
  }//GEN-LAST:event_smoothnessTextFieldActionPerformed

  private void speedTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_speedTextFieldActionPerformed
        if (speedChanging) return;
        speedChanging = true;
        speedSlider.setValue(decodeSpeed(evt));
        update();
        speedChanging = false;
  }//GEN-LAST:event_speedTextFieldActionPerformed

  private void smoothnessSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_smoothnessSliderStateChanged
        if (smoothnessChanging) return;
        smoothnessChanging = true;
        smoothnessTextField.setText(encodeSmoothness(evt));
        update();
        smoothnessChanging = false;
  }//GEN-LAST:event_smoothnessSliderStateChanged

  private void speedSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_speedSliderStateChanged
        if (speedChanging) return;
        speedChanging = true;
        speedTextField.setText(encodeSpeed(evt));
        update();
        speedChanging = false;
  }//GEN-LAST:event_speedSliderStateChanged

    private String encodeSpeed(javax.swing.event.ChangeEvent evt) {
        JSlider s = speedSlider;
        int v = s.getValue();
        double speed = (double) Math.pow(10.0, ((double) (v + 50))/50.0);
        NumberFormat form = NumberFormat.getInstance();
        form.setMaximumFractionDigits(0);
        form.setGroupingUsed(false);
        String speedText = form.format(speed);
        return speedText;
    }
    
    private static final double LOG10 = Math.log(10.0);
    // private int decodeSpeed(java.awt.event.ActionEvent evt)
    private int decodeSpeed(java.util.EventObject evt)
        throws NumberFormatException {
        JTextField t = speedTextField;
        double v = Double.parseDouble(t.getText());
        if (v <= 0)
            throw new NumberFormatException("Number must be positive");
        int p = (int) Math.round(-50.0 + 50.0 * Math.log(v)/LOG10);
        return p;
    }
    
    private String encodeSmoothness(javax.swing.event.ChangeEvent evt) {
        JSlider s = smoothnessSlider;
        int v = s.getValue();
        double smoothness = (double) Math.pow(10.0, ((double) (v - 50))/50.0);
        NumberFormat form = NumberFormat.getInstance();
        form.setMaximumFractionDigits(2);
        form.setGroupingUsed(false);
        String smoothnessText = form.format(smoothness);
        return smoothnessText;
    }
    
    // private int decodeSmoothness(java.awt.event.ActionEvent evt)
    private int decodeSmoothness(java.util.EventObject evt)
        throws NumberFormatException {
        JTextField t = smoothnessTextField;
        double v = Double.parseDouble(t.getText());
        if (v <= 0.0F)
            throw new NumberFormatException("Number must be positive");
        int p = (int) Math.round(50.0 + 50.0 * Math.log(v)/LOG10);
        return p;
    }

    private void errorPopup(Exception e) {
        JOptionPane.showMessageDialog(null, e, "Animation Settings Error",
                                      JOptionPane.ERROR_MESSAGE);
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel speedLabel;
    private javax.swing.JLabel smoothnessLabel;
    private javax.swing.JCheckBox antiAliasCheckBox;
    private javax.swing.JSlider speedSlider;
    private javax.swing.JSlider smoothnessSlider;
    private javax.swing.JLabel startAnimationLabel;
    private javax.swing.JTextField speedTextField;
    private javax.swing.JTextField smoothnessTextField;
    private javax.swing.JTextField startAnimationTextField;
    // End of variables declaration//GEN-END:variables

}