/* * Copyright (c) 2009 The Jackson Laboratory * * This software was developed by Gary Churchill's Lab at The Jackson * Laboratory (see http://research.jax.org/faculty/churchill). * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software. If not, see <http://www.gnu.org/licenses/>. */ package org.jax.qtl.scan.gui; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.jax.qtl.scan.ScanCommandBuilder; import org.jax.util.TextWrapper; /** * A small panel for editing the convergence parameters of a scan command * @author <A HREF="mailto:keith.sheppard@jax.org">Keith Sheppard</A> */ public class ConvergenceParametersPanel extends ScanCommandEditorPanel { /** * every {@link java.io.Serializable} is supposed to have one of these */ private static final long serialVersionUID = -4254037720193218387L; /** * our logger */ private static final Logger LOG = Logger.getLogger( ConvergenceParametersPanel.class.getName()); /** * the scan command that this panel edits */ private final ScanCommandBuilder scanCommand; /** * a handle for the spinner model that controls the max iterations parameter */ private final SpinnerNumberModel maximumIterationsModel; /** * Constructor * @param scanCommand * the scan command that this panel edits */ public ConvergenceParametersPanel(ScanCommandBuilder scanCommand) { this.scanCommand = scanCommand; this.maximumIterationsModel = new SpinnerNumberModel( 4000, 0, Integer.MAX_VALUE, 500); this.initComponents(); this.postGuiInit(); } /** * Do the GUI initialization that isn't taken care of by the GUI builder * code */ private void postGuiInit() { // update the spinner model to behave how we want it to this.maximumIterationsSpinner.setModel(this.maximumIterationsModel); this.maximumIterationsModel.addChangeListener( new ChangeListener() { public void stateChanged(ChangeEvent e) { ConvergenceParametersPanel.this.convergenceParametersUpdated(); } }); this.convergenceToleranceTextField.getDocument().addDocumentListener( new DocumentListener() { public void changedUpdate(DocumentEvent e) { ConvergenceParametersPanel.this.convergenceParametersUpdated(); } public void insertUpdate(DocumentEvent e) { ConvergenceParametersPanel.this.convergenceParametersUpdated(); } public void removeUpdate(DocumentEvent e) { ConvergenceParametersPanel.this.convergenceParametersUpdated(); } }); } /** * Respond to a convergence updated event. */ private void convergenceParametersUpdated() { if(this.useDefaultsCheckBox.isSelected()) { this.scanCommand.setConvergenceTolerance(null); this.scanCommand.setMaximumNumberOfIterations(null); } else { try { double convergenceTolerance = Double.parseDouble(this.convergenceToleranceTextField.getText().trim()); this.scanCommand.setConvergenceTolerance(convergenceTolerance); this.fireCommandModified(); } catch (NumberFormatException ex) { LOG.log(Level.FINE, "convergence tolerance isn't formatted as a number (user error)", ex); } this.scanCommand.setMaximumNumberOfIterations( this.maximumIterationsModel.getNumber().intValue()); } this.fireCommandModified(); } /** * {@inheritDoc} */ @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); // pass the enabled flag down to our contained components this.componentsUpdated(); } /** * Refresh the enabled state of the components */ private void componentsUpdated() { if(this.isEnabled()) { this.useDefaultsCheckBox.setEnabled(true); boolean useDefaults = this.useDefaultsCheckBox.isSelected(); this.convergenceToleranceLabel.setEnabled(!useDefaults); this.convergenceToleranceTextField.setEnabled(!useDefaults); this.maximumIterationsLabel.setEnabled(!useDefaults); this.maximumIterationsSpinner.setEnabled(!useDefaults); } else { this.useDefaultsCheckBox.setEnabled(false); this.convergenceToleranceLabel.setEnabled(false); this.convergenceToleranceTextField.setEnabled(false); this.maximumIterationsLabel.setEnabled(false); this.maximumIterationsSpinner.setEnabled(false); } } /** * 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("all") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { useDefaultsCheckBox = new javax.swing.JCheckBox(); maximumIterationsLabel = new javax.swing.JLabel(); maximumIterationsSpinner = new javax.swing.JSpinner(); convergenceToleranceLabel = new javax.swing.JLabel(); convergenceToleranceTextField = new javax.swing.JTextField(); useDefaultsCheckBox.setSelected(true); useDefaultsCheckBox.setText("Use Default Convergence Parameters"); useDefaultsCheckBox.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { useDefaultsCheckBoxItemStateChanged(evt); } }); maximumIterationsLabel.setText("Maximum Number of Iterations:"); convergenceToleranceLabel.setText("Convergence Tolerance:"); convergenceToleranceTextField.setText("1e-4"); org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .addContainerGap() .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(useDefaultsCheckBox) .add(layout.createSequentialGroup() .add(maximumIterationsLabel) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(maximumIterationsSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 77, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .add(layout.createSequentialGroup() .add(convergenceToleranceLabel) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(convergenceToleranceTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 65, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))) .addContainerGap(87, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .addContainerGap() .add(useDefaultsCheckBox) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(maximumIterationsLabel) .add(maximumIterationsSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(convergenceToleranceLabel) .add(convergenceToleranceTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// </editor-fold>//GEN-END:initComponents private void useDefaultsCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_useDefaultsCheckBoxItemStateChanged this.convergenceParametersUpdated(); this.componentsUpdated(); }//GEN-LAST:event_useDefaultsCheckBoxItemStateChanged // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel convergenceToleranceLabel; private javax.swing.JTextField convergenceToleranceTextField; private javax.swing.JLabel maximumIterationsLabel; private javax.swing.JSpinner maximumIterationsSpinner; private javax.swing.JCheckBox useDefaultsCheckBox; // End of variables declaration//GEN-END:variables /** * Validate the data in this panel. * @return * true if the validation is successful */ public boolean validateData() { String message = null; String toleranceText = this.convergenceToleranceTextField.getText().trim(); if(this.isEnabled() && !this.useDefaultsCheckBox.isSelected()) { if(toleranceText.length() == 0) { message = "Tolerance cannot be empty unless the \"use " + "defaults\" checkbox is selected"; } else { try { Double.parseDouble(toleranceText); } catch(NumberFormatException ex) { message = "Could not parse tolerance \"" + toleranceText + "\" as a floating point number"; } } } if(message != null) { JOptionPane.showMessageDialog( this, TextWrapper.wrapText( message, TextWrapper.DEFAULT_DIALOG_COLUMN_COUNT), "Validation Failed", JOptionPane.WARNING_MESSAGE); return false; } else { return true; } } /** * {@inheritDoc} */ @Override protected ScanCommandBuilder getScanCommand() { return this.scanCommand; } }