/*
 *  Draco Econometrics
 *  Copyright (C) 2006-2007 Approximatrix, LLC
 *  http://www.approximatrix.com
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.approximatrix.draco.fit.ui;

import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JTextField;

import java.awt.Component;
import java.awt.Dialog;
import javax.swing.JScrollPane;
import javax.swing.JOptionPane;
import java.awt.BorderLayout;

import java.util.ArrayList;

import com.approximatrix.draco.application.ApplicationManager;
import com.approximatrix.draco.application.worker.WorkerEvent;
import com.approximatrix.draco.datamodel.IndepDepTableModel;
import com.approximatrix.draco.datamodel.StatTableModel;
import com.approximatrix.draco.fit.LSFit;
import com.approximatrix.draco.fit.LSIterative;
import com.approximatrix.draco.fit.RunLS;
import com.approximatrix.draco.fit.RunLSAutocorrelation;
import com.approximatrix.draco.fit.ui.statistics.DurbinWatsonStatisticMenuItem;
import com.approximatrix.draco.fit.ui.statistics.ExtendedStatisticsMenu;
import com.approximatrix.draco.general.ui.InfoWindow;
import com.approximatrix.draco.general.ui.MatrixView;
import com.approximatrix.draco.io.XMLio.AnalysisLoadStore;

import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JTable;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;


/**
 * Least Squares Fit base class providing the necessary routines for 
 * displaying the least squares fit dialog.  Most routines necessary for
 * modifying the dialog have been provided.  This class can be extended to be
 * used in cases where a simple least-squares fit is needed as an
 * intermediate step, such as in a two-stage least squares fit problem.  The
 * routine has two internal subclasses for dealing with the actual fit itself
 * and the same fit with autocorrellation.
 * 
 * @author Jeffrey Armstrong
 * @version	1.0
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class LeastSquaresFit extends FitChildDialog  {

	/** The default dialog name */
	private static final String DIALOG_NAME = "Least Squares Fit";
	
	/** The default results dialog name */
	private static final String DEFAULT_RESULTS_NAME = "Regression Results";
	
	/** The string for requesting topical help */
	private static final String HELP_KEY = "lsfit";
	
	private javax.swing.JPanel jContentPane = null;

	private StatTableModel current_model;
	
	private JMenuBar jJMenuBar = null;
	private JMenu ls_fit_menu = null;
	private JMenu ls_fit_info_menu = null;
	private JMenuItem m_compute_regress = null;
	private JMenuItem m_gen_column = null;
	private JMenuItem m_cov_matrix = null;
	private JMenu ls_options_menu = null;
	private JTable selection_table = null;
	private JScrollPane jScrollPane = null;
	private ButtonGroup variance_buttongroup = null;
	private ButtonGroup autocorrelation_method_buttongroup = null;
	
	private IndepDepTableModel selection_model = null;
	
	//private LSFit analysis = null;
	
	private JMenu ls_options_var_menu = null;
	private JRadioButtonMenuItem var_ols_radmenu = null;
	private JRadioButtonMenuItem var_wht_radmenu = null;
	private JMenuItem m_output_residuals = null;
	private JCheckBoxMenuItem ls_options_include_constant = null;
	private JCheckBoxMenuItem ls_options_ignore_condition = null;
	private ExtendedStatisticsMenu ls_options_extout_menu = null;
	private JCheckBoxMenuItem extout_DWstat_checkmenu = null;
	private JMenu ls_options_ac_menu = null;
	private JCheckBoxMenuItem ac_use_checkmenu = null;
	private JMenu ac_technique_menu = null;
	private JMenuItem ac_set_level_menuitem = null;
	private JRadioButtonMenuItem actech_co_radiomenu = null;
	private JRadioButtonMenuItem actech_hl_radiomenu = null;
	private JMenuItem actech_set_iterations_menuitem = null;
	
	// Autocorrellation parameters
	private int ac_number_iteration = 1;
	private double ac_tolerance = 0.01;
	private double ac_relaxation = 1.0;
	private int ac_order = 2;
	private IterativeProgress ac_solver_progress_dialog = null;
	
	/**
	 * This is the default constructor
	 */
	public LeastSquaresFit() {
		super(DIALOG_NAME, 
				true, //resizable
				true, //closable
				true, //maximizable
				true);
	}
	
	/** 
	 * Constructor which accepts a StatTableModel input from which data is
	 * extracted for fitting.
	 * 
	 * @param information	A statistics data model to pull info from
	 */
	public LeastSquaresFit(StatTableModel information) {
		super(DIALOG_NAME, 
				true, //resizable
				true, //closable
				true, //maximizable
				true);
		
		current_model = information;
		
		initialize();
		
		if(information == null) {
			System.err.println("Error with input to LeastSquaresFit");
		}
		
	}
	
	/**
	 * This method initializes the dialog.
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
		this.setName("least_squares_dialog");
		this.setTitle(DIALOG_NAME);
		this.setSize(334, 235);
		this.setContentPane(getJContentPane());
		
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		
		// In order to initialize all menu/toolbars
		this.getMenuItems();
		this.getToolbarButtons();
		
		//this.addWindowListener(new java.awt.event.WindowAdapter() { 
		//	public void windowClosing(java.awt.event.WindowEvent e) {    
		//		close_window();
		//	}
		//});
		
		// Set up the variance buttons
		variance_buttongroup = new ButtonGroup();
		variance_buttongroup.add(var_ols_radmenu);
		variance_buttongroup.add(var_wht_radmenu);
		
		// Set up autocorrelation buttons
		autocorrelation_method_buttongroup = new ButtonGroup();
		autocorrelation_method_buttongroup.add(actech_co_radiomenu);
		autocorrelation_method_buttongroup.add(actech_hl_radiomenu);
		actech_co_radiomenu.setSelected(true);
		actech_hl_radiomenu.setEnabled(false);
		ac_number_iteration = IterationControl.GetDefaultIterations();
		ac_tolerance = IterationControl.GetDefaultTolerance();
		ac_relaxation = IterationControl.GetDefaultRelaxation();

		// Put information in the list
		String[] indep_items = new String[current_model.getColumnCount()];
		for(int i=0;i<current_model.getColumnCount();i++) {
			indep_items[i] = current_model.getColumnName(i);
		}		
		
		selection_model = new IndepDepTableModel(indep_items);
		selection_table.setModel(selection_model);

	}
	
	/**
	 * Provides access to the currently stored StatTableModel.
	 * 
	 * @return StatTableModel
	 */
	public StatTableModel getCurrentModel() {
		return current_model;
	}
	
	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private javax.swing.JPanel getJContentPane() {
		if(jContentPane == null) {
			jContentPane = new javax.swing.JPanel();
			jContentPane.setLayout(new java.awt.BorderLayout());
			
			jContentPane.add(getJScrollPane(), java.awt.BorderLayout.CENTER);
		}
		return jContentPane;
	}
	
	/**
	 * Performs and returns the least squares fit object based on the
	 * internally stored StatTableModel selection_model.
	 * 
	 * @return RunLS
	 */
	private void do_fit() {		
		String dep = selection_model.getDependentVariable();
		String[] indep_cols = selection_model.getIndependentVariables();
		
		if(dep == null) {
			JOptionPane.showMessageDialog(jContentPane,"Please select a dependent variable",  "Data Error", JOptionPane.ERROR_MESSAGE);
		}
		if(indep_cols == null) {
			JOptionPane.showMessageDialog(jContentPane,"Please select an independent variable",  "Data Error", JOptionPane.ERROR_MESSAGE);
		}

		// If we got this far, we must actually be running the analysis
		selection_table.setEnabled(false); // To block any further changes
		ls_options_menu.setEnabled(false);
		
		int var_type = RunLS.VAR_OLS;
		if(var_wht_radmenu.isSelected()) {
			var_type = RunLS.VAR_WHITE;
		}
		
		boolean include_constant = ls_options_include_constant.isSelected();
		boolean ignore_condition = ls_options_ignore_condition.isSelected();
		
		if(ac_use_checkmenu.isSelected()) {
			int ac_method = 0;
			
			// Select the autocorrellation method
			if(actech_co_radiomenu.isSelected()) {
				ac_method = RunLSAutocorrelation.CO_METHOD;
			} else if(actech_hl_radiomenu.isSelected()) {
				ac_method = RunLSAutocorrelation.HL_METHOD;
			}
			
			// First iteration
			analysis = new RunLSAutocorrelation(indep_cols,
					                            dep,
					                            current_model,
					                            var_type,
					                            include_constant,
					                            ac_method,
					                            ac_order,
					                        	ac_relaxation);
			analysis.setExtendedStatistics(this.getLs_options_extout_menu().getStatistics());
			super.performAnalysis((LSIterative)analysis, ac_number_iteration, ac_tolerance);
			//return analysis;
			
		} else {
			analysis = new RunLS(indep_cols,dep,current_model,var_type,include_constant,ignore_condition);
			analysis.setExtendedStatistics(this.getLs_options_extout_menu().getStatistics());
			this.performAnalysis(analysis);			
		}
	}
	
	
	/**
	 * This method initializes jJMenuBar	
	 * 	
	 * @return javax.swing.JMenuBar	
	 */    
	private JMenuBar getJJMenuBar() {
		if (jJMenuBar == null) {
			jJMenuBar = new JMenuBar();
			jJMenuBar.add(getLs_fit_menu());
			jJMenuBar.add(getLs_fit_info_menu());
			jJMenuBar.add(getLs_options_menu());
		}
		return jJMenuBar;
	}
	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */    
	private JMenu getLs_fit_menu() {
		if (ls_fit_menu == null) {
			ls_fit_menu = new JMenu();
			ls_fit_menu.setText("Perform Fit");
			ls_fit_menu.add(getM_compute_regress());
			ls_fit_menu.add(getM_gen_column());
		}
		return ls_fit_menu;
	}
	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */    
	private JMenu getLs_fit_info_menu() {
		if (ls_fit_info_menu == null) {
			ls_fit_info_menu = new JMenu();
			ls_fit_info_menu.setText("Supporting Data");
			ls_fit_info_menu.add(getM_cov_matrix());
			ls_fit_info_menu.add(getM_output_residuals());
		}
		return ls_fit_info_menu;
	}
	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */    
	protected JMenuItem getM_compute_regress() {
		if (m_compute_regress == null) {
			m_compute_regress = new JMenuItem();
			m_compute_regress.setText("Compute Regression...");
			m_compute_regress.addActionListener(new java.awt.event.ActionListener() { 
				public void actionPerformed(java.awt.event.ActionEvent e) {    
					if(analysis == null) {
						do_fit();
					} else { // && !super.ac_use_checkmenu.isSelected()) {
						
						String results = analysis.getResults();
						LeastSquaresFit.this.getMainWindow().openWindow(new InfoWindow(results,false));
					
					}
				}
			});
		}
		return m_compute_regress;
	}
	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */    
	protected JMenuItem getM_gen_column() {
		if (m_gen_column == null) {
			m_gen_column = new JMenuItem();
			m_gen_column.setText("Generate Column Data");
			m_gen_column.addActionListener(new java.awt.event.ActionListener() { 
				public void actionPerformed(java.awt.event.ActionEvent e) {   
										
					if(selection_model.getIndependentVariables() != null ) {
						
						if(analysis == null) {
							JOptionPane.showMessageDialog(jContentPane,"Please compute the regression first.",  ApplicationManager.APP_NAME+" Error", JOptionPane.ERROR_MESSAGE);
							return;
						}
						//double[] col_data = analysis.generate_data_from_fit();
						Double[] col_data = analysis.getFittedData();
						
						StringBuffer title = new StringBuffer();
						title.append(analysis.getDependentVariable());
						title.append("_HAT");
						
						// Now that we have data, fill in a new column
						current_model.addColumn(col_data,title.toString());						
					} else {
						 JOptionPane.showMessageDialog(jContentPane,"Please select an independent variable",  ApplicationManager.APP_NAME+" Error", JOptionPane.ERROR_MESSAGE);
					}
				}
			});
		}
		return m_gen_column;
	}
	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */    
	protected JMenuItem getM_cov_matrix() {
		if (m_cov_matrix == null) {
			m_cov_matrix = new JMenuItem();
			m_cov_matrix.setText("View Covariance Matrix...");
			m_cov_matrix.addActionListener(new java.awt.event.ActionListener() { 
				public void actionPerformed(java.awt.event.ActionEvent e) {
					if(analysis == null) {
						JOptionPane.showMessageDialog(jContentPane,"Please compute the regression first.",  ApplicationManager.APP_NAME+" Error", JOptionPane.ERROR_MESSAGE);
						return;
					}
					double[][] covariances = analysis.getCovarianceMatrix();
					
					// Need data names
					String[] just_vars = analysis.getIndependentVariables();
					String[] all_names = null; 
					if(ls_options_include_constant.isSelected()) {
						all_names = new String[just_vars.length+1];
						all_names[0] = "Constant";
						for(int i=0;i<just_vars.length;i++) {
							all_names[i+1] = just_vars[i];
						}
					} else {
						all_names = new String[just_vars.length];
						for(int i=0;i<just_vars.length;i++) {
							all_names[i] = just_vars[i];
						}
					}
					LeastSquaresFit.this.getMainWindow().openWindow(
							new MatrixView("Least-Squares Covariance Matrix",
							       all_names,
								   all_names,
								   covariances));
				}
			});
		}
		return m_cov_matrix;
	}
	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */    
	protected JMenu getLs_options_menu() {
		if (ls_options_menu == null) {
			ls_options_menu = new JMenu();
			ls_options_menu.setText("Options");
			ls_options_menu.add(getLs_options_var_menu());			
			ls_options_menu.add(getLs_options_extout_menu());			
			ls_options_menu.add(getLs_options_ac_menu());
			ls_options_menu.add(getLs_options_include_constant());
			ls_options_menu.add(getLs_options_ignore_conditioning());
		}
		return ls_options_menu;
	}
	/**
	 * This method initializes jTable	
	 * 	
	 * @return javax.swing.JTable	
	 */    
	private JTable getSelection_table() {
		if (selection_table == null) {
			selection_table = new JTable();
		}
		return selection_table;
	}
	/**
	 * This method initializes jScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */    
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setViewportView(getSelection_table());
		}
		return jScrollPane;
	}
	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */    
	protected JMenu getLs_options_var_menu() {
		if (ls_options_var_menu == null) {
			ls_options_var_menu = new JMenu();
			ls_options_var_menu.setText("Variances");
			ls_options_var_menu.add(getVar_ols_radmenu());
			ls_options_var_menu.add(getVar_wht_radmenu());
		}
		return ls_options_var_menu;
	}
	/**
	 * This method initializes jRadioButtonMenuItem	
	 * 	
	 * @return javax.swing.JRadioButtonMenuItem	
	 */    
	protected JRadioButtonMenuItem getVar_ols_radmenu() {
		if (var_ols_radmenu == null) {
			var_ols_radmenu = new JRadioButtonMenuItem();
			var_ols_radmenu.setText("Ordinary Least Squares");
			var_ols_radmenu.setSelected(true);
			var_ols_radmenu.setToolTipText("Use standard Ordinary Least Squares variance estimates");
		}
		return var_ols_radmenu;
	}
	/**
	 * This method initializes jRadioButtonMenuItem	
	 * 	
	 * @return javax.swing.JRadioButtonMenuItem	
	 */    
	protected JRadioButtonMenuItem getVar_wht_radmenu() {
		if (var_wht_radmenu == null) {
			var_wht_radmenu = new JRadioButtonMenuItem();
			var_wht_radmenu.setText("White's Robust Variance Estimates");
			var_wht_radmenu.setToolTipText("Use White's more robust variance estimates");
		}
		return var_wht_radmenu;
	}
	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */    
	protected JMenuItem getM_output_residuals() {
		if (m_output_residuals == null) {
			m_output_residuals = new JMenuItem();
			m_output_residuals.setText("Output Residuals to Column");
			m_output_residuals.addActionListener(new java.awt.event.ActionListener() { 
				public void actionPerformed(java.awt.event.ActionEvent e) {    
					if(analysis == null) {
						JOptionPane.showMessageDialog(jContentPane,"Please compute the regression first.",  ApplicationManager.APP_NAME+" Error", JOptionPane.ERROR_MESSAGE);
						return;
					}
					
					current_model.addColumn(analysis.getResiduals(),"Residuals");
				}
			});
		}
		return m_output_residuals;
	}
	
	/**
	 * This method initializes jCheckBoxMenuItem	
	 * 	
	 * @return javax.swing.JCheckBoxMenuItem	
	 */    
	protected JCheckBoxMenuItem getLs_options_include_constant() {
		if (ls_options_include_constant == null) {
			ls_options_include_constant = new JCheckBoxMenuItem();
			ls_options_include_constant.setText("Include constant in model");
			ls_options_include_constant.setSelected(true);
			ls_options_include_constant.setToolTipText("Check if a constant shouldbe included in the least squares fit model");
		}
		return ls_options_include_constant;
	}
	
	protected JCheckBoxMenuItem getLs_options_ignore_conditioning() {
		if (ls_options_ignore_condition == null) {
			ls_options_ignore_condition = new JCheckBoxMenuItem();
			ls_options_ignore_condition.setText("Ignore matrix condition for solving");
			ls_options_ignore_condition.setSelected(false);
			ls_options_ignore_condition.setToolTipText("Check if a constant shouldbe included in the least squares fit model");
		}
		return ls_options_ignore_condition;
	}
	
	
	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */    
	protected ExtendedStatisticsMenu getLs_options_extout_menu() {
		if (ls_options_extout_menu == null) {
			ls_options_extout_menu = new ExtendedStatisticsMenu();
			ls_options_extout_menu.add(new DurbinWatsonStatisticMenuItem());
		}
		return ls_options_extout_menu;
	}
	/**
	 * This method initializes jCheckBoxMenuItem	
	 * 	
	 * @return javax.swing.JCheckBoxMenuItem	
	 */    
	protected JCheckBoxMenuItem getExtout_DWstat_checkmenu() {
		if (extout_DWstat_checkmenu == null) {
			extout_DWstat_checkmenu = new JCheckBoxMenuItem();
			extout_DWstat_checkmenu.setText("Durbin-Watson Statistic");
		}
		return extout_DWstat_checkmenu;
	}
	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */    
	protected JMenu getLs_options_ac_menu() {
		if (ls_options_ac_menu == null) {
			ls_options_ac_menu = new JMenu();
			ls_options_ac_menu.setText("Autocorrelation");
			ls_options_ac_menu.add(getAc_use_checkmenu());
			ls_options_ac_menu.add(getAc_technique_menu());
			ls_options_ac_menu.add(getAc_set_level_menuitem());
		}
		return ls_options_ac_menu;
	}
	/**
	 * This method initializes jCheckBoxMenuItem	
	 * 	
	 * @return javax.swing.JCheckBoxMenuItem	
	 */    
	private JCheckBoxMenuItem getAc_use_checkmenu() {
		if (ac_use_checkmenu == null) {
			ac_use_checkmenu = new JCheckBoxMenuItem();
			ac_use_checkmenu.setText("Account for Autocorrelation");
		}
		return ac_use_checkmenu;
	}
	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */    
	private JMenu getAc_technique_menu() {
		if (ac_technique_menu == null) {
			ac_technique_menu = new JMenu();
			ac_technique_menu.setText("Technique");
			ac_technique_menu.add(getActech_co_radiomenu());
			ac_technique_menu.add(getActech_hl_radiomenu());
			ac_technique_menu.add(getActech_set_iterations_menuitem());
		}
		return ac_technique_menu;
	}
	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */    
	private JMenuItem getAc_set_level_menuitem() {
		if (ac_set_level_menuitem == null) {
			ac_set_level_menuitem = new JMenuItem();
			ac_set_level_menuitem.setText("Set autoregressive level...");
			ac_set_level_menuitem.addActionListener(new java.awt.event.ActionListener() { 
				public void actionPerformed(java.awt.event.ActionEvent e) {
					
					Object[] message = new Object[2];
					message[0] = new String("Enter order of autocorrelation:");
					message[1] = new JTextField(Integer.toString(ac_order));
					int response = JOptionPane.showConfirmDialog(LeastSquaresFit.this,message,ApplicationManager.APP_NAME,JOptionPane.OK_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE);
					try {
						if(response == JOptionPane.OK_OPTION)
							ac_order = new Integer(((JTextField)message[1]).getText()).intValue();
					} catch(NumberFormatException nfe) {
						
					} catch(NullPointerException npe) {
						
					}
					
					
				}
			});
		}
		return ac_set_level_menuitem;
	}
	/**
	 * This method initializes jRadioButtonMenuItem	
	 * 	
	 * @return javax.swing.JRadioButtonMenuItem	
	 */    
	private JRadioButtonMenuItem getActech_co_radiomenu() {
		if (actech_co_radiomenu == null) {
			actech_co_radiomenu = new JRadioButtonMenuItem();
			actech_co_radiomenu.setText("Cochrane-Orcutt Method");
			actech_co_radiomenu.setSelected(true);
		}
		return actech_co_radiomenu;
	}
	/**
	 * This method initializes jRadioButtonMenuItem	
	 * 	
	 * @return javax.swing.JRadioButtonMenuItem	
	 */    
	private JRadioButtonMenuItem getActech_hl_radiomenu() {
		if (actech_hl_radiomenu == null) {
			actech_hl_radiomenu = new JRadioButtonMenuItem();
			actech_hl_radiomenu.setText("Hildreth-Liu Iterative Method");
		}
		return actech_hl_radiomenu;
	}
	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */    
	private JMenuItem getActech_set_iterations_menuitem() {
		if (actech_set_iterations_menuitem == null) {
			actech_set_iterations_menuitem = new JMenuItem();
			actech_set_iterations_menuitem.setText("Set number of iterations/threshhold...");
			actech_set_iterations_menuitem.addActionListener(new java.awt.event.ActionListener() { 
				public void actionPerformed(java.awt.event.ActionEvent e) {
					IterationControl temp = new IterationControl();
					int result = JOptionPane.showConfirmDialog(LeastSquaresFit.this,
															   temp,
															   "Interation Controls",
															   JOptionPane.OK_CANCEL_OPTION,
															   JOptionPane.PLAIN_MESSAGE);
					if(result == 0) {
						ac_number_iteration = temp.getIterations();
						ac_tolerance = temp.getTolerance();
						ac_relaxation = temp.getRelaxation();
					}
				}
			});
		}
		return actech_set_iterations_menuitem;
	}

	public JTable getTable() {
		return selection_table;
	}
	
	// IterativeProgressParent routines
	/** Notifies the parent that the iterative computation has been completed.
	 * This function is only used if autocorrellation is accounted for.
	 * 
	 */
	public void notifyComplete() {
		this.analysis = (RunLSAutocorrelation)ac_solver_progress_dialog.getAnalysis();
		ac_solver_progress_dialog = null;
		this.displayResults();
	}	
	
//	private void displayResults() {
//		if(analysis != null) {
//			String results = analysis.getResults();
//			LeastSquaresFit.this.getMainWindow().openWindow(new InfoWindow(DEFAULT_RESULTS_NAME,results,false,true));
//		} else {
//			JOptionPane.showMessageDialog(this,"Regression failed!","Iterative Regression",JOptionPane.ERROR_MESSAGE);
//		}
//	}
	
	/** Returns the main window of this dialog for modal control
	 * of the iterative progress window.
	 * 
	 * @return the MainWindow object enclosing this dialog
	 */
	public JFrame getParentFrame() {
		return this.getMainWindow();
	}
	
	/** Retuns the analysis as an LSFit object
	 * 
	 * @return a valid, complete LSFit object
	 */
	public LSFit getAnalysis() {
		return analysis;
	}
	
	/** Used for restoring an LSFit analysis to a dialog
	 * 
	 * @param values a valid, loaded AnalysisLoadStore dataset
	 */
	public void setAnalysis(AnalysisLoadStore data) {
		analysis = new RunLS();
		analysis.setLoadedAnalysis(data, current_model);
		
		// Fill in the check boxes
		String[] indep = analysis.getIndependentVariables();
		for(int i=0;i<indep.length;i++) ((IndepDepTableModel)selection_table.getModel()).setIndepenedentChecked(indep[i]);
		((IndepDepTableModel)selection_table.getModel()).setDepenedentChecked(analysis.getDependentVariable());
		((IndepDepTableModel)selection_table.getModel()).fireTableDataChanged();
		
		// Make the table unchangeable
		selection_table.setEnabled(false); // To block any further changes
		ls_options_menu.setEnabled(false);
		
		if(data.getName() != null)
			this.setTitle(data.getName());
	}

	/** The menus needed for a ls fit dialog.
	 * 
	 * @return an array of JMenu items for the main window menu
	 * @see com.approximatrix.draco.application.ChildFrame#getMenuItems()
	 */
	public JMenu[] getMenuItems() {
		if(menuItems == null) {
			ArrayList items = new ArrayList();
			
			items.add(getLs_fit_menu());
			items.add(getLs_fit_info_menu());
			items.add(getLs_options_menu());
			
			menuItems = new JMenu[items.size()];
			items.toArray(menuItems);
		}
		return menuItems;
	}

	/** This dialog does not currently use any toolbar buttons...
	 * 
	 * @return null, as there are no toolbar buttons
	 * @see com.approximatrix.draco.application.ChildFrame#getToolbarButtons()
	 */
	public Component[] getToolbarButtons() {
		return null;
	}

	/** Returns the help key for the Least Squares Fit window
	 * 
	 * @return the proper help key, defined by HELP_KEY
	 * @see #HELP_KEY
	 * @see com.approximatrix.draco.application.ChildFrame#getHelpKey()
	 */
	public String getHelpKey() {
		return HELP_KEY;
	}
	
	protected void check_extended() {
		if(analysis == null) return;
		
		// Durbin-Watson
		if(this.getExtout_DWstat_checkmenu().isSelected())
			((RunLS)analysis).setExtendedStatistic(RunLS.EXTSTAT_DURBIN_WATSON,true);
	}

	/** Returns the name of the results window
	 * 
	 * @return a String containing the default results window name
	 */
	protected String getResultsWindowName() {
		return DEFAULT_RESULTS_NAME;
	}
	
 }  //  @jve:decl-index=0:visual-constraint="121,30"
