/FileExtraction/Java_unseen/crisis-economics_CRISIS/CRISIS/src/eu/crisis_economics/abm/dashboard/Page_Parameters.java
/*
 * This file is part of CRISIS, an economics simulator.
 * 
 * Copyright (C) 2015 AITIA International, Inc.
 * Copyright (C) 2015 Ross Richardson
 * Copyright (C) 2015 John Kieran Phillips
 * Copyright (C) 2015 Ariel Y. Hoffman
 *
 * CRISIS 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.
 *
 * CRISIS 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 CRISIS.  If not, see <http://www.gnu.org/licenses/>.
 */
package eu.crisis_economics.abm.dashboard;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.InputVerifier;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.ListSelectionModel;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import javax.xml.bind.JAXBElement;

import org.apache.commons.lang3.StringUtils;
import org.jdesktop.swingx.JXLabel;
import org.reflections.ReflectionUtils;
import org.reflections.Reflections;
import org.reflections.ReflectionsException;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ai.aitia.meme.gui.Wizard;
import ai.aitia.meme.gui.Wizard.Button;
import ai.aitia.meme.gui.Wizard.IWizardPage;
import ai.aitia.meme.paramsweep.batch.IModelInformation.ModelInformationException;
import ai.aitia.meme.paramsweep.batch.output.RecordableInfo;
import ai.aitia.meme.paramsweep.batch.param.AbstractParameterInfo;
import ai.aitia.meme.paramsweep.batch.param.IncrementalParameterInfo;
import ai.aitia.meme.paramsweep.batch.param.ParameterNode;
import ai.aitia.meme.paramsweep.batch.param.ParameterTree;
import ai.aitia.meme.paramsweep.gui.info.ISubmodelGUIInfo;
import ai.aitia.meme.paramsweep.gui.info.MasonChooserParameterInfo;
import ai.aitia.meme.paramsweep.gui.info.MasonIntervalParameterInfo;
import ai.aitia.meme.paramsweep.gui.info.ParameterInfo;
import ai.aitia.meme.paramsweep.gui.info.SubmodelInfo;
import ai.aitia.meme.paramsweep.internal.platform.IGUIController.RunOption;
import ai.aitia.meme.paramsweep.internal.platform.InfoConverter;
import ai.aitia.meme.paramsweep.internal.platform.PlatformSettings;
import ai.aitia.meme.paramsweep.plugin.IIntelliContext;
import ai.aitia.meme.paramsweep.plugin.IIntelliDynamicMethodPlugin;
import ai.aitia.meme.paramsweep.utils.Utilities;
import ai.aitia.meme.utils.GUIUtils;
import ai.aitia.meme.utils.Utils.Pair;
import aurelienribon.ui.css.Style;

import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.looks.common.RGBGrayFilter;
import com.wordpress.tips4java.ListAction;

import eu.crisis_economics.abm.dashboard.ga.DashboardIntelliContext;
import eu.crisis_economics.abm.dashboard.generated.Combination;
import eu.crisis_economics.abm.dashboard.generated.DefaultParameter;
import eu.crisis_economics.abm.dashboard.generated.GeneralParameter;
import eu.crisis_economics.abm.dashboard.generated.Model;
import eu.crisis_economics.abm.dashboard.generated.ModelType;
import eu.crisis_economics.abm.dashboard.generated.ObjectFactory;
import eu.crisis_economics.abm.dashboard.generated.Parameter;
import eu.crisis_economics.abm.dashboard.generated.ParameterType;
import eu.crisis_economics.abm.dashboard.generated.SubmodelParameter;
import eu.crisis_economics.abm.model.ConfigurationComponent;
import eu.crisis_economics.abm.model.Layout;

/**
 * @author Tamás Máhr
 *
 */
public class Page_Parameters implements IWizardPage, IIconsInHeader, ActionListener {
	
	//====================================================================================================
	// members
	
	private static final String CSS_ID_BREADCRUMB = "#breadcrumb";
	private static final String LOADING_MODEL_ID = "LOADING_MODEL";
	private static final String PARAMETERS_PANEL_ID = "PARAMETERS_PANEL";
	private static final String UPDATE_CHARTS_LABEL_TEXT = " Update charts in real-time";
	private static final String DISPLAY_ADVANCED_CHARTS_LABEL_TEXT = " Show individual agents' measures";
	private static final String NUMBER_OF_TURNS_LABEL_TEXT = " Terminate simulation at time-step";
	private static final String NUMBER_OF_TIMESTEPS_TO_IGNORE_LABEL_TEXT = " Start charting after time-step";

	static final String BROWSE_BUTTON_TEXT = "Browse";
	
	private static final String DECORATION_IMAGE = "Audio_mixer_faders.jpg";
	static final int DECORATION_IMAGE_WIDTH = 300;
	private static final int PARAMETER_DESCRIPTION_LABEL_HEIGHT = 200;
	private static final int PARAMETER_DESCRIPTION_LABEL_WIDTH = 400;
	
	private static final int MAX_SIZE_OF_SUBPARAMETER_COMBOBOX = 100;
	
	static final int ICON_WIDTH_AND_HEIGHT = 25;
	
	private static final ImageIcon PARAMETER_ADD_ICON_DIS = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_silver_right.png")).
															getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon PARAMETER_ADD_ICON = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_green_right.png")).
														getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon PARAMETER_ADD_ICON_RO = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_red_right.png")).
														   getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	
	private static final ImageIcon PARAMETER_REMOVE_ICON_DIS = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_silver_left.png")).
														   	   getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon PARAMETER_REMOVE_ICON = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_green_left.png")).
														   getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon PARAMETER_REMOVE_ICON_RO = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_red_left.png")).
															  getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
		
	private static final ImageIcon PARAMETER_UP_ICON_DIS = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_silver_up.png")).
														   getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon PARAMETER_UP_ICON = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_green_up.png")).
													   getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon PARAMETER_UP_ICON_RO = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_red_up.png")).
														  getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
																																				
	private static final ImageIcon PARAMETER_DOWN_ICON_DIS = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_silver_down.png")).
															 getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon PARAMETER_DOWN_ICON = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_green_down.png")).
														 getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon PARAMETER_DOWN_ICON_RO = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_red_down.png")).
															getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));

	private static final ImageIcon PARAMETER_BOX_REMOVE = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/remove_box.png")).getImage().
														  getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	
	private static final ImageIcon SHOW_SUBMODEL_ICON_DIS = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_silver_right.png")).
			getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon SHOW_SUBMODEL_ICON = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_green_right.png")).
			getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));
	private static final ImageIcon SHOW_SUBMODEL_ICON_RO = new ImageIcon(new ImageIcon(Dashboard.class.getResource("icons/arrow_button_metal_red_right.png")).
			getImage().getScaledInstance(ICON_WIDTH_AND_HEIGHT,ICON_WIDTH_AND_HEIGHT,Image.SCALE_SMOOTH));

	private static final int GASEARCH_GUI_TABINDEX = 2;
	private static final int PARAMSWEEP_GUI_TABINDEX = 1;
	private static final int SINGLE_RUN_GUI_TABINDEX = 0;

	private static final String ACTIONCOMMAND_ADD_PARAM = "ADD_PARAM",
								ACTIONCOMMAND_REMOVE_PARAM = "REMOVE_PARAM",
								ACTIONCOMMAND_ADD_BOX = "ADD_BOX",
								ACTIONCOMMAND_REMOVE_BOX = "REMOVE_BOX",
								ACTIONCOMMAND_MOVE_UP = "MOVE_UP",
								ACTIONCOMMAND_MOVE_DOWN = "MOVE_DOWN",
								ACTIONCOMMAND_EDIT = "EDIT",
								ACTIONCOMMAND_BROWSE = "BROWSE",
								ACTIONCOMMAND_SHOW_SUBMODEL = "SHOW_SUBMODEL";

	private static final String TITLE = "Parameters";
	private static final String ORIGINAL_TEXT = "Select a parameter to modify its settings.";
	private static final String INFO_TEXT = "Please select the parameters to run";

	private static Logger log = LoggerFactory.getLogger(Page_Parameters.class);

	private final Dashboard dashboard;
	private IModelHandler currentModelHandler;
	private final DWizard wizard;
	private final Container container;
	private JScrollPane parametersScrollPane;
	
	private DefaultMutableTreeNode parameterValueComponentTree = new DefaultMutableTreeNode();
	private final Map<String,List<Class<?>>> possibleTypesCache = new HashMap<String,List<Class<?>>>();

	private JFormattedTextField numberOfTurnsField;
	private JFormattedTextField numberOfTurnsFieldPSW;
	private JFormattedTextField numberTimestepsIgnored;
	private JFormattedTextField numberTimestepsIgnoredPSW;
	private JCheckBox onLineChartsCheckBox;
	private JCheckBox advancedChartsCheckBox;
//	private JCheckBox onLineChartsCheckBoxPSW;

	private Popup errorPopup;

	private JRadioButton constDef;
	private JRadioButton listDef;
	private JRadioButton incrDef;
	private JTextField constDefField;
	private JTextArea listDefArea;
	private JTextField incrStartValueField;
	private JTextField incrEndValueField;
	private JTextField incrStepField;
	private JComboBox enumDefBox;
	private JComboBox submodelTypeBox;
	private JButton cancelButton;
	private JButton modifyButton;
	private JTextField fileTextField;
	private JButton fileBrowseButton;

	private JLabel editedParameterText;
	private JPanel sweepPanel;
	private JPanel rightMiddle;
	private JTabbedPane tabbedPane;

	private JList parameterList;
	private JXLabel parameterDescriptionLabel;

	private GASearchPanelModel gaSearchHandler;
	private GASearchPanel gaSearchPanel;
	
	private JPanel singleRunParametersPanel;
	
	private DefaultMutableTreeNode editedNode;
	private JTree editedTree;
	private List<ParameterCombinationGUI> parameterTreeBranches = new ArrayList<ParameterCombinationGUI>(5);
	private List<ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>> batchParameters;

	private JPanel combinationsPanel;
	private JScrollPane combinationsScrPane;

	protected String currentDirectory = "";
	protected Breadcrumb breadcrumb;
	
	/**
	 * The list of active submodel buttons that need to be turned red. The index in the list corresponds to the submodel level.
	 */
	protected List<JButton> submodelButtons = new ArrayList<JButton>();
	
	//====================================================================================================
	// methods

	//----------------------------------------------------------------------------------------------------
	public Page_Parameters(final DWizard wizard, final Dashboard dashboard) {
		this.wizard = wizard;
		this.dashboard = dashboard;
		
		container = initContainer();
		
		Style.apply(container, dashboard.getCssStyle());
	}

	//----------------------------------------------------------------------------------------------------
	/** {@inheritDoc} 
	 */
	@Override
	public String getInfoText(final Wizard w) {
		return w.getArrowsHeader(INFO_TEXT);
	}

	//----------------------------------------------------------------------------------------------------
	@Override
	public Icon getIcon() {
		return new ImageIcon(getClass().getResource("icons/params.png"));
	}
	
	//----------------------------------------------------------------------------------------------------
	/** {@inheritDoc} 
	 */
	@Override
	public Container getPanel() {
		
		return container;
	}

	//----------------------------------------------------------------------------------------------------
	private Container initContainer() {
		JPanel containerPanel = new JPanel(new CardLayout());
		JLabel loadingModelLabel = new JLabel("Loading model...");
		loadingModelLabel.setHorizontalAlignment(SwingConstants.CENTER);
		containerPanel.add(loadingModelLabel, LOADING_MODEL_ID);
		tabbedPane = new JTabbedPane();
		containerPanel.add(tabbedPane, PARAMETERS_PANEL_ID);
		
		// create two number of turns field
		numberOfTurnsField = new JFormattedTextField();
		numberOfTurnsField.setFocusLostBehavior(JFormattedTextField.COMMIT);
		numberOfTurnsField.setInputVerifier(new InputVerifier() {
			
			@Override
			public boolean verify(final JComponent input) {
				if (!checkNumberOfTurnsField(true)){
					final PopupFactory popupFactory = PopupFactory.getSharedInstance();
					final Point locationOnScreen = numberOfTurnsField.getLocationOnScreen();
					final JLabel message = new JLabel("Please specify a (possibly floating point) number!");
					message.setBorder(new LineBorder(Color.RED, 2, true));
					if (errorPopup != null)
						errorPopup.hide();
					errorPopup = popupFactory.getPopup(numberOfTurnsField, message, locationOnScreen.x - 10, locationOnScreen.y - 30);
					
					errorPopup.show();
					
					return false;
				} else {
					if (errorPopup != null){
						errorPopup.hide();
						errorPopup = null;
					}
					return true;
				}
			}
		});
		numberOfTurnsField.setText(String.valueOf(Dashboard.NUMBER_OF_TURNS));
		numberOfTurnsField.setToolTipText("The turn when the simulation should stop specified as an integer value.");
		numberOfTurnsField.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent e) {
				wizard.clickDefaultButton();
			}
		});

		numberOfTurnsFieldPSW = new JFormattedTextField();
		numberOfTurnsFieldPSW.setFocusLostBehavior(JFormattedTextField.COMMIT);
		numberOfTurnsFieldPSW.setInputVerifier(new InputVerifier() {
			
			@Override
			public boolean verify(final JComponent input) {
				if (!checkNumberOfTurnsField(false)){
					final PopupFactory popupFactory = PopupFactory.getSharedInstance();
					final Point locationOnScreen = numberOfTurnsFieldPSW.getLocationOnScreen();
					final JLabel message = new JLabel("Please specify a (possibly floating point) number!");
					message.setBorder(new LineBorder(Color.RED, 2, true));
					if (errorPopup != null)
						errorPopup.hide();
					errorPopup = popupFactory.getPopup(numberOfTurnsFieldPSW, message, locationOnScreen.x - 10, locationOnScreen.y - 30);
					
					errorPopup.show();
					
					return false;
				} else {
					if (errorPopup != null){
						errorPopup.hide();
						errorPopup = null;
					}
					return true;
				}
			}
		});
		numberOfTurnsFieldPSW.setText(String.valueOf(Dashboard.NUMBER_OF_TURNS));
		numberOfTurnsFieldPSW.setToolTipText("The turn when the simulation should stop specified as an integer value.");
		numberOfTurnsFieldPSW.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent e) {
				wizard.clickDefaultButton();
			}
		});

		// create two number of time-steps to ignore field
		numberTimestepsIgnored = new JFormattedTextField();
		numberTimestepsIgnored.setFocusLostBehavior(JFormattedTextField.COMMIT);
		numberTimestepsIgnored.setInputVerifier(new InputVerifier() {
			
			@Override
			public boolean verify(final JComponent input) {
				if (!checkNumberTimestepsIgnored(true)){
					final PopupFactory popupFactory = PopupFactory.getSharedInstance();
					final Point locationOnScreen = numberTimestepsIgnored.getLocationOnScreen();
					final JLabel message = new JLabel("Please specify an integer number!");
					message.setBorder(new LineBorder(Color.RED, 2, true));
					if (errorPopup != null)
						errorPopup.hide();
					errorPopup = popupFactory.getPopup(numberTimestepsIgnored, message, locationOnScreen.x - 10, locationOnScreen.y - 30);
					
					errorPopup.show();
					
					return false;
				} else {
					if (errorPopup != null){
						errorPopup.hide();
						errorPopup = null;
					}
					return true;
				}
			}
		});
		numberTimestepsIgnored.setText(String.valueOf(Dashboard.NUMBER_OF_TIMESTEPS_TO_IGNORE));
		numberTimestepsIgnored.setToolTipText("The turn when the simulation should start charting specified as an integer value.");
		numberTimestepsIgnored.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent e) {
				wizard.clickDefaultButton();
			}
		});

		numberTimestepsIgnoredPSW = new JFormattedTextField();
		numberTimestepsIgnoredPSW.setFocusLostBehavior(JFormattedTextField.COMMIT);
		numberTimestepsIgnoredPSW.setInputVerifier(new InputVerifier() {
			
			@Override
			public boolean verify(final JComponent input) {
				if (!checkNumberTimestepsIgnored(false)){
					final PopupFactory popupFactory = PopupFactory.getSharedInstance();
					final Point locationOnScreen = numberTimestepsIgnoredPSW.getLocationOnScreen();
					final JLabel message = new JLabel("Please specify an integer number!");
					message.setBorder(new LineBorder(Color.RED, 2, true));
					if (errorPopup != null)
						errorPopup.hide();
					errorPopup = popupFactory.getPopup(numberTimestepsIgnoredPSW, message, locationOnScreen.x - 10, locationOnScreen.y - 30);
					
					errorPopup.show();
					
					return false;
				} else {
					if (errorPopup != null){
						errorPopup.hide();
						errorPopup = null;
					}
					return true;
				}
			}
		});
		numberTimestepsIgnoredPSW.setText(String.valueOf(Dashboard.NUMBER_OF_TIMESTEPS_TO_IGNORE));
		numberTimestepsIgnoredPSW.setToolTipText("The turn when the simulation should start charting specified as an integer value.");
		numberTimestepsIgnoredPSW.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent e) {
				wizard.clickDefaultButton();
			}
		});
		
		onLineChartsCheckBox = new JCheckBox();
//		onLineChartsCheckBoxPSW = new JCheckBox();
		advancedChartsCheckBox = new JCheckBox();
		advancedChartsCheckBox.setSelected(true);
		
		// create the scroll pane for the simple parameter setting page
		JLabel label = null;
		label = new JLabel(new ImageIcon(new ImageIcon(getClass().getResource(DECORATION_IMAGE)).getImage().getScaledInstance(DECORATION_IMAGE_WIDTH, -1, Image.SCALE_SMOOTH)));
		Style.registerCssClasses(label, Dashboard.CSS_CLASS_COMMON_PANEL);
		parametersScrollPane = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		parametersScrollPane.setBorder(null);
		parametersScrollPane.setViewportBorder(null);
		
		breadcrumb = new Breadcrumb();
		Style.registerCssClasses(breadcrumb, CSS_ID_BREADCRUMB);
		
		singleRunParametersPanel = new ScrollableJPanel(new SizeProvider() {
			
			@Override
			public int getHeight() {
				Component component = tabbedPane.getSelectedComponent();
				if (component == null) {
					return 0;
				}
				JScrollBar scrollBar = parametersScrollPane.getHorizontalScrollBar();
				return component.getSize().height - breadcrumb.getHeight() - (scrollBar.isVisible() ? scrollBar.getPreferredSize().height : 0);
			}
			
			@Override
			public int getWidth() {
				final int hScrollBarWidth = parametersScrollPane.getHorizontalScrollBar().getPreferredSize().width;
				final int width = dashboard.getSize().width - Page_Parameters.DECORATION_IMAGE_WIDTH - hScrollBarWidth;
				return width;
			}
		});
		BoxLayout boxLayout = new BoxLayout(singleRunParametersPanel, BoxLayout.X_AXIS);
		singleRunParametersPanel.setLayout(boxLayout);
		parametersScrollPane.setViewportView(singleRunParametersPanel);

		JPanel breadcrumbPanel = new JPanel(new BorderLayout());
		breadcrumbPanel.add(breadcrumb, BorderLayout.NORTH);
		breadcrumbPanel.add(parametersScrollPane, BorderLayout.CENTER);
		
		final JPanel simpleForm = FormsUtils.build("p ~ p:g", 
				"01 t:p",
				label, breadcrumbPanel).getPanel();
		Style.registerCssClasses(simpleForm, Dashboard.CSS_CLASS_COMMON_PANEL);
		
		tabbedPane.add("Single run", simpleForm);

		// create the form for the parameter sweep setting page
		tabbedPane.add("Parameter sweep", createParamsweepGUI());
		
		gaSearchHandler = new GASearchHandler(currentModelHandler);
		gaSearchPanel = new GASearchPanel(gaSearchHandler,this);
		tabbedPane.add("Genetic Algorithm Search", gaSearchPanel);
		
		return containerPanel;
	}

	//----------------------------------------------------------------------------------------------------
	@SuppressWarnings("serial")
	private JPanel createParamsweepGUI() {
		
		// left
		parameterList = new JList();
		parameterList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		new ListAction(parameterList,new AbstractAction() {
         public void actionPerformed(final ActionEvent event) {
				final AvailableParameter selectedParameter = (AvailableParameter) parameterList.getSelectedValue();
				addParameterToTree(new AvailableParameter[] { selectedParameter },parameterTreeBranches.get(0));
				enableDisableParameterCombinationButtons();
			}
		});
		parameterList.addListSelectionListener(new ListSelectionListener() {
         public void valueChanged(ListSelectionEvent e) {
				if (!parameterList.isSelectionEmpty()) {
					boolean success = true;
					if (editedNode != null) 
						success = modify();
					
					if (success) {
						cancelAllSelectionBut(parameterList);
						resetSettings();
						updateDescriptionField(parameterList.getSelectedValues());
						enableDisableParameterCombinationButtons();
					} else
						parameterList.clearSelection();
				}
			}
		});
		
		final JScrollPane parameterListPane = new JScrollPane(parameterList);
		parameterListPane.setBorder(BorderFactory.createTitledBorder("")); // for rounded border
		parameterListPane.setPreferredSize(new Dimension(300,300));
		
		final JPanel parametersPanel = FormsUtils.build("p ' p:g",
										  "[DialogBorder]00||" + 
														"12||" +
														"34||" +
//														"56||" + 
														"55||" +
														"66 f:p:g",
														new FormsUtils.Separator("<html><b>General parameters</b></html>"),
														NUMBER_OF_TURNS_LABEL_TEXT,numberOfTurnsFieldPSW,
														NUMBER_OF_TIMESTEPS_TO_IGNORE_LABEL_TEXT,numberTimestepsIgnoredPSW,
//														UPDATE_CHARTS_LABEL_TEXT,onLineChartsCheckBoxPSW,
														new FormsUtils.Separator("<html><b>Model parameters</b></html>"),
														parameterListPane).getPanel();
		
		combinationsPanel = new JPanel(new GridLayout(0,1,5,5)); 
		combinationsScrPane = new JScrollPane(combinationsPanel,ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		combinationsScrPane.setBorder(null);
		combinationsScrPane.setPreferredSize(new Dimension(550,500));

		parameterDescriptionLabel = new JXLabel();
		parameterDescriptionLabel.setLineWrap(true);
		parameterDescriptionLabel.setVerticalAlignment(SwingConstants.TOP);
		final JScrollPane descriptionScrollPane = new JScrollPane(parameterDescriptionLabel);
		descriptionScrollPane.setBorder(BorderFactory.createTitledBorder(null,"Description",TitledBorder.LEADING,TitledBorder.BELOW_TOP));
		descriptionScrollPane.setPreferredSize(new Dimension(PARAMETER_DESCRIPTION_LABEL_WIDTH, PARAMETER_DESCRIPTION_LABEL_HEIGHT));
		descriptionScrollPane.setViewportBorder(null);
		
		final JButton addNewBoxButton = new JButton("Add new combination"); 
		addNewBoxButton.setActionCommand(ACTIONCOMMAND_ADD_BOX);
		
		final JPanel left = FormsUtils.build("p ~ f:p:g ~ p",
				 "011 f:p:g ||" +
				 "0_2 p",
				 parametersPanel,combinationsScrPane,
				 addNewBoxButton).getPanel();
		left.setBorder(BorderFactory.createTitledBorder(null,"Specify parameter combinations",TitledBorder.LEADING,TitledBorder.BELOW_TOP));
		Style.registerCssClasses(left, Dashboard.CSS_CLASS_COMMON_PANEL);
		
		final JPanel leftAndDesc = new JPanel(new BorderLayout());
		leftAndDesc.add(left,BorderLayout.CENTER);
		leftAndDesc.add(descriptionScrollPane,BorderLayout.SOUTH);
		Style.registerCssClasses(leftAndDesc,Dashboard.CSS_CLASS_COMMON_PANEL);
		
		// right
		editedParameterText = new JLabel(ORIGINAL_TEXT);
		editedParameterText.setPreferredSize(new Dimension(280,40));
		constDef = new JRadioButton("Constant");
		listDef = new JRadioButton("List");
		incrDef = new JRadioButton("Increment");
		
		final JPanel rightTop = FormsUtils.build("p:g",
				   "[DialogBorder]0||" +
						   		 "1||" + 
					             "2||" +
					             "3",
	                editedParameterText,
					constDef,
					listDef,
					incrDef).getPanel();
		
		Style.registerCssClasses(rightTop, Dashboard.CSS_CLASS_COMMON_PANEL);
		
		constDefField = new JTextField();
		final JPanel constDefPanel = FormsUtils.build("p ~ p:g",
								 "[DialogBorder]01 p",
								 "Constant value: ",CellConstraints.TOP,constDefField).getPanel();
		
		listDefArea = new JTextArea();
		final JScrollPane listDefScr = new JScrollPane(listDefArea,ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		final JPanel listDefPanel = FormsUtils.build("p ~ p:g",
								"[DialogBorder]01|" +
								              "_1 f:p:g||" +
								              "_2 p",
								"Value list: ",listDefScr,
								"(Separate values with spaces!)").getPanel();
		
		incrStartValueField = new JTextField();
		incrEndValueField = new JTextField();
		incrStepField = new JTextField();
		
		final JPanel incrDefPanel = FormsUtils.build("p ~ p:g",
								"[DialogBorder]01||" +
											  "23||" +
											  "45",
											  "Start value: ",incrStartValueField,
											  "End value: ",incrEndValueField,
											  "Step: ",incrStepField).getPanel();
		
		enumDefBox = new JComboBox(new DefaultComboBoxModel());
		final JPanel enumDefPanel = FormsUtils.build("p ~ p:g", 
								"[DialogBorder]01 p", 
								"Constant value:", CellConstraints.TOP, enumDefBox).getPanel();
		
		submodelTypeBox = new JComboBox();
		final JPanel submodelTypePanel = FormsUtils.build("p ~ p:g",
											"[DialogBorder]01",
											"Constant value:", CellConstraints.TOP,submodelTypeBox).getPanel();
		
		fileTextField = new JTextField();
		fileTextField.addKeyListener(new KeyAdapter() {
			public void keyTyped(final KeyEvent e) {
				final char character = e.getKeyChar();
				final File file = new File(Character.isISOControl(character) ? fileTextField.getText() : fileTextField.getText() + character);
				fileTextField.setToolTipText(file.getAbsolutePath());
			}
		});
		fileBrowseButton = new JButton(BROWSE_BUTTON_TEXT);
		fileBrowseButton.setActionCommand(ACTIONCOMMAND_BROWSE);
		final JPanel fileDefPanel = FormsUtils.build("p ~ p:g ~p",
									   "[DialogBorder]012",
									   "File:",fileTextField,fileBrowseButton).getPanel();
		
		constDefPanel.setName("CONST");
		listDefPanel.setName("LIST");
		incrDefPanel.setName("INCREMENT");
		enumDefPanel.setName("ENUM");
		submodelTypePanel.setName("SUBMODEL");
		fileDefPanel.setName("FILE");
		
		Style.registerCssClasses(constDefPanel,Dashboard.CSS_CLASS_COMMON_PANEL);
		Style.registerCssClasses(listDefPanel,Dashboard.CSS_CLASS_COMMON_PANEL);
		Style.registerCssClasses(incrDefPanel,Dashboard.CSS_CLASS_COMMON_PANEL);
		Style.registerCssClasses(enumDefPanel,Dashboard.CSS_CLASS_COMMON_PANEL);
		Style.registerCssClasses(submodelTypePanel,Dashboard.CSS_CLASS_COMMON_PANEL);
		Style.registerCssClasses(fileDefPanel,Dashboard.CSS_CLASS_COMMON_PANEL);
		
		rightMiddle = new JPanel(new CardLayout());
		Style.registerCssClasses(rightMiddle, Dashboard.CSS_CLASS_COMMON_PANEL);
		rightMiddle.add(constDefPanel,constDefPanel.getName());
		rightMiddle.add(listDefPanel,listDefPanel.getName());
		rightMiddle.add(incrDefPanel,incrDefPanel.getName());
		rightMiddle.add(enumDefPanel, enumDefPanel.getName());
		rightMiddle.add(submodelTypePanel,submodelTypePanel.getName());
		rightMiddle.add(fileDefPanel,fileDefPanel.getName());
		
		modifyButton = new JButton("Modify");
		cancelButton = new JButton("Cancel");
		
		final JPanel rightBottom = FormsUtils.build("p:g p ~ p ~ p:g",
							  "[DialogBorder]_01_ p",
							  modifyButton,cancelButton).getPanel();
		
		Style.registerCssClasses(rightBottom, Dashboard.CSS_CLASS_COMMON_PANEL);
		
		final JPanel right = new JPanel(new BorderLayout());
		right.add(rightTop,BorderLayout.NORTH);
		right.add(rightMiddle,BorderLayout.CENTER);
		right.add(rightBottom,BorderLayout.SOUTH);
		right.setBorder(BorderFactory.createTitledBorder(null,"Parameter settings",TitledBorder.LEADING,TitledBorder.BELOW_TOP));

		Style.registerCssClasses(right, Dashboard.CSS_CLASS_COMMON_PANEL);

		// the whole paramsweep panel
		
		final JPanel content = FormsUtils.build("p:g p",
								   "01 f:p:g",
								   leftAndDesc,right).getPanel();
		Style.registerCssClasses(content, Dashboard.CSS_CLASS_COMMON_PANEL);
		
		sweepPanel = new JPanel();
		Style.registerCssClasses(sweepPanel, Dashboard.CSS_CLASS_COMMON_PANEL);
		sweepPanel.setLayout(new BorderLayout());
		final JScrollPane sp = new JScrollPane(content);
		sp.setBorder(null);
		sp.setViewportBorder(null);
		sweepPanel.add(sp,BorderLayout.CENTER);
		
		GUIUtils.createButtonGroup(constDef,listDef,incrDef);
		constDef.setSelected(true);
		constDef.setActionCommand("CONST");
		listDef.setActionCommand("LIST");
		incrDef.setActionCommand("INCREMENT");
		
		constDefField.setActionCommand("CONST_FIELD");
		incrStartValueField.setActionCommand("START_FIELD");
		incrEndValueField.setActionCommand("END_FIELD");
		incrStepField.setActionCommand("STEP_FIELD");
		
		modifyButton.setActionCommand("EDIT");
		cancelButton.setActionCommand("CANCEL");
		
		listDefArea.setLineWrap(true);
		listDefArea.setWrapStyleWord(true);
		listDefScr.setPreferredSize(new Dimension(100,200));
		
		GUIUtils.addActionListener(this,modifyButton,cancelButton,constDef,listDef,incrDef,constDefField,incrStartValueField,incrEndValueField,incrStepField,
								   addNewBoxButton,submodelTypeBox,fileBrowseButton);
		
		return sweepPanel;
	}
	
	//----------------------------------------------------------------------------------------------------
	private JPanel createAParameterBox(final boolean first) {
		
		final JLabel runLabel = new JLabel("<html><b>Number of runs:</b> 0</html>");
		final JLabel warningLabel = new JLabel();
		
		final JButton closeButton = new JButton();
		closeButton.setOpaque(false);
	    closeButton.setBorder(null);
	    closeButton.setFocusable(false);
	    
	    if (!first) {
		    closeButton.setRolloverIcon(PARAMETER_BOX_REMOVE);
		    closeButton.setRolloverEnabled(true);
		    closeButton.setIcon(RGBGrayFilter.getDisabledIcon(closeButton,PARAMETER_BOX_REMOVE));
		    closeButton.setActionCommand(ACTIONCOMMAND_REMOVE_BOX);
	    }
	    
	    final JScrollPane treeScrPane = new JScrollPane();
	    final DefaultMutableTreeNode treeRoot = new DefaultMutableTreeNode();
	    final JTree tree = new JTree(treeRoot);
	    ToolTipManager.sharedInstance().registerComponent(tree);
	    
		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		tree.setCellRenderer(new ParameterBoxTreeRenderer());
		tree.addTreeSelectionListener(new TreeSelectionListener() {
			public void valueChanged(final TreeSelectionEvent e) {
				final TreePath selectionPath = tree.getSelectionPath();
				boolean success = true;
				if (editedNode != null && (selectionPath == null || !editedNode.equals(selectionPath.getLastPathComponent()))) 
					success = modify();
				
				if (success) {
					if (selectionPath != null) {
						cancelAllSelectionBut(tree);
						final DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectionPath.getLastPathComponent();
						if (!node.equals(editedNode)) {
							ParameterInATree userObj = null;
							final DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
							if (!node.isRoot() && selectionPath.getPathCount() == model.getPathToRoot(node).length) {
								userObj = (ParameterInATree) node.getUserObject();
								final ParameterInfo info = userObj.info;
								editedNode = node;
								editedTree = tree;
								edit(info);
							} else {
								tree.setSelectionPath(null);
								if (cancelButton.isEnabled())
									cancelButton.doClick();
								resetSettings();
								enableDisableSettings(false);
								editedNode = null;
								editedTree = null;
							}
							
							updateDescriptionField(userObj);
						} else
							updateDescriptionField();
						
					} else
						updateDescriptionField();
					
					enableDisableParameterCombinationButtons();
				} else {
					final DefaultTreeModel model = (DefaultTreeModel) editedTree.getModel();
					final DefaultMutableTreeNode storedEditedNode = editedNode;
					editedNode = null;
					tree.setSelectionPath(null);
					editedNode = storedEditedNode;
					editedTree.setSelectionPath(new TreePath(model.getPathToRoot(editedNode)));
				}
			}
		});

	    treeScrPane.setViewportView(tree);
	    treeScrPane.setBorder(null);
	    treeScrPane.setViewportBorder(null);
		treeScrPane.setPreferredSize(new Dimension(450,250));
	    
		final JButton upButton = new JButton();
		upButton.setOpaque(false);
		upButton.setRolloverEnabled(true);
		upButton.setIcon(PARAMETER_UP_ICON);
		upButton.setRolloverIcon(PARAMETER_UP_ICON_RO);
		upButton.setDisabledIcon(PARAMETER_UP_ICON_DIS);
		upButton.setBorder(null);
		upButton.setToolTipText("Move up the selected parameter");
		upButton.setActionCommand(ACTIONCOMMAND_MOVE_UP);
		
		final JButton downButton = new JButton();
		downButton.setOpaque(false);
		downButton.setRolloverEnabled(true);
		downButton.setIcon(PARAMETER_DOWN_ICON);
		downButton.setRolloverIcon(PARAMETER_DOWN_ICON_RO);
		downButton.setDisabledIcon(PARAMETER_DOWN_ICON_DIS);
		downButton.setBorder(null);
		downButton.setToolTipText("Move down the selected parameter");
		downButton.setActionCommand(ACTIONCOMMAND_MOVE_DOWN);

		
		final JPanel mainPanel = FormsUtils.build("~ f:p:g ~ p ~ r:p",
												  "012||" +
												  "333||" +
												  "44_||" + 
												  "445||" +
												  "446||" + 
												  "44_ f:p:g",
												  runLabel,first ? "" : warningLabel,first ? warningLabel : closeButton,
												  new FormsUtils.Separator(""),
												  treeScrPane,
												  upButton,
												  downButton).getPanel(); 
				
				
		mainPanel.setBorder(BorderFactory.createTitledBorder(""));
		
		final JButton addButton = new JButton();
		addButton.setOpaque(false);
		addButton.setRolloverEnabled(true);
		addButton.setIcon(PARAMETER_ADD_ICON);
		addButton.setRolloverIcon(PARAMETER_ADD_ICON_RO);
		addButton.setDisabledIcon(PARAMETER_ADD_ICON_DIS);
		addButton.setBorder(null);
		addButton.setToolTipText("Add selected parameter");
		addButton.setActionCommand(ACTIONCOMMAND_ADD_PARAM);
		
		final JButton removeButton = new JButton();
		removeButton.setOpaque(false);
		removeButton.setRolloverEnabled(true);
		removeButton.setIcon(PARAMETER_REMOVE_ICON);
		removeButton.setRolloverIcon(PARAMETER_REMOVE_ICON_RO);
		removeButton.setDisabledIcon(PARAMETER_REMOVE_ICON_DIS);
		removeButton.setBorder(null);
		removeButton.setToolTipText("Remove selected parameter");
		removeButton.setActionCommand(ACTIONCOMMAND_REMOVE_PARAM);
		
		final JPanel result = FormsUtils.build("p ~ f:p:g",
											   "_0 f:p:g||" +
											   "10 p ||" +
											   "20 p||" +
											   "_0 f:p:g",
											   mainPanel,
											   addButton,
											   removeButton).getPanel();
		
		Style.registerCssClasses(result,Dashboard.CSS_CLASS_COMMON_PANEL);
		
		final ParameterCombinationGUI pcGUI = new ParameterCombinationGUI(tree,treeRoot,runLabel,warningLabel,addButton,removeButton,upButton,downButton);
		parameterTreeBranches.add(pcGUI);
		
		final ActionListener boxActionListener = new ActionListener() {
			
			//====================================================================================================
			// methods
			
			//----------------------------------------------------------------------------------------------------
			public void actionPerformed(final ActionEvent e) {
				final String cmd = e.getActionCommand();
				
				if (ACTIONCOMMAND_ADD_PARAM.equals(cmd)) 
					handleAddParameter(pcGUI);
				else if (ACTIONCOMMAND_REMOVE_PARAM.equals(cmd)) 
					handleRemoveParameter(tree);
				else if (ACTIONCOMMAND_REMOVE_BOX.equals(cmd)) 
					handleRemoveBox(tree);
				else if (ACTIONCOMMAND_MOVE_UP.equals(cmd)) 
					handleMoveUp();
				else if (ACTIONCOMMAND_MOVE_DOWN.equals(cmd))
					handleMoveDown();
			}

			//----------------------------------------------------------------------------------------------------
			private void handleAddParameter(final ParameterCombinationGUI pcGUI) {
				final Object[] selectedValues = parameterList.getSelectedValues();
				if (selectedValues != null && selectedValues.length > 0) {
					final AvailableParameter[] params = new AvailableParameter[selectedValues.length];
					System.arraycopy(selectedValues,0,params,0,selectedValues.length);
					addParameterToTree(params,pcGUI);
					enableDisableParameterCombinationButtons();
				}
			}
			
			//----------------------------------------------------------------------------------------------------
			private void handleRemoveParameter(final JTree tree) {
				final TreePath selectionPath = tree.getSelectionPath();
				if (selectionPath != null) {
					cancelButton.doClick();
					
					final DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectionPath.getLastPathComponent();
					if (!node.isRoot()) {
						final DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) node.getParent();
						if (parentNode.isRoot()) { 
							removeParameter(tree,node,parentNode);
							enableDisableParameterCombinationButtons();
						}
					}
				}
			}
			
			//----------------------------------------------------------------------------------------------------
			private void handleRemoveBox(final JTree tree) {
				final int answer = Utilities.askUser(dashboard,false,"Comfirmation","This operation deletes the combination.", 
																			  		"All related parameter returns back to the list on the left side.",
																			  		"Are you sure?");
				if (answer == 1) {
					final DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();

					if (tree.getSelectionCount() > 0) {
						editedNode = null;
						tree.setSelectionPath(null);
						if (cancelButton.isEnabled())
							cancelButton.doClick();
					}
					
					final DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
					for (int i = 0;i < root.getChildCount();++i) {
						final DefaultMutableTreeNode node = (DefaultMutableTreeNode) root.getChildAt(i);
						removeParameter(tree,node,root);
					}
					
					enableDisableParameterCombinationButtons();

					parameterTreeBranches.remove(pcGUI);
					combinationsPanel.remove(result);
					combinationsPanel.revalidate();
					
					updateNumberOfRuns();
				}
			}
			
			//----------------------------------------------------------------------------------------------------
			private void removeParameter(final JTree tree, final DefaultMutableTreeNode node, final DefaultMutableTreeNode parentNode) {
				final ParameterInATree userObj = (ParameterInATree) node.getUserObject();
				final ParameterInfo originalInfo = findOriginalInfo(userObj.info);
				if (originalInfo != null) {
					final DefaultListModel model = (DefaultListModel) parameterList.getModel();
					model.addElement(new AvailableParameter(originalInfo, currentModelHandler.getModelClass()));
					final DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();
					treeModel.removeNodeFromParent(node);
					updateNumberOfRuns();
					tree.expandPath(new TreePath(treeModel.getPathToRoot(parentNode)));
				} else 
					throw new IllegalStateException("Parameter " + userObj.info.getName() + " is not found in the model.");
			}
			
			//----------------------------------------------------------------------------------------------------
			private void handleMoveUp() {
				final TreePath selectionPath = tree.getSelectionPath();
				if (selectionPath != null) {
					boolean success = true;
					if (editedNode != null) 
						success = modify();
					
					if (success) {
						final DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectionPath.getLastPathComponent();
						final DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();
						
						if (parent == null || parent.getFirstChild().equals(node)) {
							tree.setSelectionPath(null); // we need this to preserve the state of the parameter settings panel
							tree.setSelectionPath(new TreePath(node.getPath()));
							return;
						}
						
						final int index = parent.getIndex(node);
						final DefaultTreeModel treemodel = (DefaultTreeModel) tree.getModel();
						treemodel.removeNodeFromParent(node);
						treemodel.insertNodeInto(node,parent,index - 1);
						tree.setSelectionPath(new TreePath(node.getPath()));
					}

				}
			}
				
			//----------------------------------------------------------------------------------------------------
			private void handleMoveDown() {
				final TreePath selectionPath = tree.getSelectionPath();
				if (selectionPath != null) {
					boolean success = true;
					if (editedNode != null) 
						success = modify();
					
					if (success) {
						final DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectionPath.getLastPathComponent();
						final DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();
						
						if (parent == null || parent.getLastChild().equals(node)) {
							tree.setSelectionPath(null); // we need this to preserve the state of the parameter settings panel
							tree.setSelectionPath(new TreePath(node.getPath()));
							return;
						}
						
						final int index = parent.getIndex(node);
						final DefaultTreeModel treemodel = (DefaultTreeModel) tree.getModel();
						treemodel.removeNodeFromParent(node);
						treemodel.insertNodeInto(node,parent,index + 1);
						tree.setSelectionPath(new TreePath(node.getPath()));
					}
				}
			}
		};
		
		GUIUtils.addActionListener(boxActionListener,closeButton,upButton,downButton,addButton,removeButton);
		
		result.setPreferredSize(new Dimension(500,250));
		enableDisableParameterCombinationButtons();
		
		Style.apply(result, dashboard.getCssStyle());

		return result;
	}
	
	//----------------------------------------------------------------------------------------------------
	private void addParameterToTree(final AvailableParameter[] parameters, final ParameterCombinationGUI pcGUI) {
		final DefaultListModel listModel = (DefaultListModel) parameterList.getModel();
		final DefaultTreeModel treeModel = (DefaultTreeModel) pcGUI.tree.getModel();
		final DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
		
		for (final AvailableParameter parameter : parameters) {
			listModel.removeElement(parameter);
			final ParameterInfo selectedInfo = parameter.info;
			final DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(new ParameterInATree(selectedInfo, currentModelHandler.getModelClass()));
			treeModel.insertNodeInto(newNode,root,root.getChildCount());
			
			if (selectedInfo instanceof SubmodelInfo) {
				final SubmodelInfo sInfo = (SubmodelInfo) selectedInfo;
				if (sInfo.getActualType() != null) {
					addSubParametersToTree(sInfo,pcGUI.tree,newNode);
					pcGUI.tree.expandPath(new TreePath(treeModel.getPathToRoot(newNode)));				
				}
			}
		}

		updateNumberOfRuns();
		pcGUI.tree.expandPath(new TreePath(treeModel.getPathToRoot(root)));
	}

 
	//----------------------------------------------------------------------------------------------------
	public void resetParamsweepGUI(){
		changeText(null, null);
		constDef.setSelected(true);
		constDefField.setText(null);
		incrStartValueField.setText(null);
		incrEndValueField.setText(null);
		incrStepField.setText(null);
		listDefArea.setText(null);
		fileTextField.setText(null);
		fileTextField.setToolTipText(null);
		combinationsPanel.removeAll();
		parameterTreeBranches.clear();
		combinationsPanel.add(createAParameterBox(true));
		combinationsPanel.revalidate();
	}
	
	//----------------------------------------------------------------------------------------------------
	/** {@inheritDoc} 
	 */
	@Override
	public boolean isEnabled(final Button button) {
		switch (button){
		case BACK:
			return true;
			
		case NEXT:
			return true;
			
		case CANCEL: // this is the charts page
			return true;
			
		case FINISH:
			return false;
			
		case CUSTOM:
			return false;
		}
		return false;
	}

	//----------------------------------------------------------------------------------------------------
	/** {@inheritDoc} 
	 */
	@Override
	public boolean onButtonPress(final Button button) {
		if (Button.NEXT.equals(button)) {
			ParameterTree parameterTree = null;
			if (tabbedPane.getSelectedIndex() == SINGLE_RUN_GUI_TABINDEX) {
				currentModelHandler.setIntelliMethodPlugin(null);
				parameterTree = new ParameterTree();
				final Set<ParameterInfo> invalids = new HashSet<ParameterInfo>();
				
				@SuppressWarnings("rawtypes")
				final Enumeration treeValues = parameterValueComponentTree.breadthFirstEnumeration();
				treeValues.nextElement(); // root element
				while (treeValues.hasMoreElements()) {
					final DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeValues.nextElement();
					@SuppressWarnings("unchecked")
					final Pair<ParameterInfo,JComponent> userData = (Pair<ParameterInfo,JComponent>) node.getUserObject();
					final ParameterInfo parameterInfo = userData.getFirst();
					final JComponent valueContainer = userData.getSecond();
					
					if (parameterInfo instanceof ISubmodelGUIInfo) {
						final ISubmodelGUIInfo sgi = (ISubmodelGUIInfo) parameterInfo;
						if (sgi.getParent() != null) {
							final DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) node.getParent();
							@SuppressWarnings("unchecked")
							final Pair<ParameterInfo,JComponent> parentUserData = (Pair<ParameterInfo,JComponent>) parentNode.getUserObject();
							final SubmodelInfo parentParameterInfo = (SubmodelInfo) parentUserData.getFirst();
							if (invalids.contains(parentParameterInfo) || !classEquals(parentParameterInfo.getActualType(),sgi.getParentValue())) {
								invalids.add(parameterInfo);
								continue;
							}
						}
					}
					
					if (parameterInfo.isBoolean()){
						final JCheckBox checkBox = (JCheckBox) valueContainer;
						parameterInfo.setValue(checkBox.isSelected());
					} else if (parameterInfo.isEnum()) {
						final JComboBox comboBox = (JComboBox) valueContainer;
						parameterInfo.setValue(comboBox.getSelectedItem());
					} else if (parameterInfo instanceof MasonChooserParameterInfo) {
						final JComboBox comboBox = (JComboBox) valueContainer;
						parameterInfo.setValue(comboBox.getSelectedIndex());
					} else if (parameterInfo instanceof SubmodelInfo) {
						// we don't need the SubmodelInfo parameters anymore (all descendant parameters are in the tree too)
						// but we need to check that an actual type is provided
						final SubmodelInfo smi = (SubmodelInfo) parameterInfo;
						final JComboBox comboBox = (JComboBox) ((JPanel)valueContainer).getComponent(0);
						final ClassElement selected = (ClassElement) comboBox.getSelectedItem();
						smi.setActualType(selected.clazz, selected.instance);
						
						if (smi.getActualType() == null) {
							final String errorMsg = "Please select a type from the dropdown list of " + smi.getName().replaceAll("([A-Z])"," $1");
							JOptionPane.showMessageDialog(wizard, new JLabel(errorMsg), "Error", JOptionPane.ERROR_MESSAGE);
							return false;
						}
						
						//continue;
					} else if (parameterInfo.isFile()) {
						final JTextField textField = (JTextField) valueContainer.getComponent(0);
						if (textField.getText().trim().isEmpty())
							log.warn("Empty string was specified as file parameter " + parameterInfo.getName().replaceAll("([A-Z])"," $1"));
						
						final File file = new File(textField.getToolTipText());
						if (!file.exists()) {
							final String errorMsg = "Please specify an existing file parameter " + parameterInfo.getName().replaceAll("([A-Z])"," $1");
							JOptionPane.showMessageDialog(wizard,new JLabel(errorMsg),"Error",JOptionPane.ERROR_MESSAGE);
							return false;
						}
						
						parameterInfo.setValue(ParameterInfo.getValue(textField.getToolTipText(),parameterInfo.getType()));
					} else if (parameterInfo instanceof MasonIntervalParameterInfo) {
						final JTextField textField = (JTextField) valueContainer.getComponent(0);
						parameterInfo.setValue(ParameterInfo.getValue(textField.getText().trim(),parameterInfo.getType()));
					} else {
						final JTextField textField = (JTextField) valueContainer;
						parameterInfo.setValue(ParameterInfo.getValue(textField.getText(),parameterInfo.getType()));
						if ("String".equals(parameterInfo.getType()) && parameterInfo.getValue() == null)
							parameterInfo.setValue(textField.getText().trim());
					}
					
					final AbstractParameterInfo<?> batchParameterInfo = InfoConverter.parameterInfo2ParameterInfo(parameterInfo);
					parameterTree.addNode(batchParameterInfo);
				}
				
				dashboard.setOnLineCharts(onLineChartsCheckBox.isSelected());
				dashboard.setDisplayAdvancedCharts(advancedChartsCheckBox.isSelected());
			}
			
			if (tabbedPane.getSelectedIndex() == PARAMSWEEP_GUI_TABINDEX) {
				currentModelHandler.setIntelliMethodPlugin(null);
				boolean success = true;
				if (editedNode != null) 
					success = modify();
				
				if (success) {
					String invalidInfoName = checkInfos(true); 
					if (invalidInfoName != null) {
						Utilities.userAlert(sweepPanel,"Please select a type from the dropdown list of " + invalidInfoName);
						return false;
					}
					
					invalidInfoName = checkInfos(false);
					if (invalidInfoName != null) {
						Utilities.userAlert(sweepPanel,"Please specify a file for parameter " + invalidInfoName);
						return false;
					}
					
					if (needWarning()) {
						final int result = Utilities.askUser(sweepPanel,false,"Warning","There are two or more combination boxes that contains non-constant parameters." +
													   " Parameters are unsynchronized:", "simulation may exit before all parameter values are assigned.",
													   " ","To explore all possible combinations you must use only one combination box.",
													   " ","Do you want to run simulation with these parameter settings?");  
						if (result == 0) {
							return false;
						}
					}
					
					try {
							parameterTree = createParameterTreeFromParamSweepGUI();
							
							final ParameterNode rootNode = parameterTree.getRoot();
							dumpParameterTree(rootNode);
							
	//						dashboard.setOnLineCharts(onLineChartsCheckBoxPSW.isSelected());
					} catch (final ModelInformationException e) {
						JOptionPane.showMessageDialog(wizard, new JLabel(e.getMessage()), "Error while creating runs", JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
						return false;
					}
				} else return false;
			}
			
			if (tabbedPane.getSelectedIndex() == GASEARCH_GUI_TABINDEX) {
				final IIntelliDynamicMethodPlugin gaPlugin = (IIntelliDynamicMethodPlugin)gaSearchHandler;
				currentModelHandler.setIntelliMethodPlugin(gaPlugin);
				boolean success = gaSearchPanel.closeActiveModification();
				
				if (success) {
					String invalidInfoName = checkInfosInGeneTree(); 
					if (invalidInfoName != null) {
						Utilities.userAlert(sweepPanel,"Please select a type from the dropdown list of " + invalidInfoName);
						return false;
					} 
					
					final String[] errors = gaSearchHandler.checkGAModel();
					if (errors != null) {
						Utilities.userAlert(sweepPanel,(Object[])errors);
						return false;
					}
					
					final DefaultMutableTreeNode parameterTreeRootNode = new DefaultMutableTreeNode();
					final IIntelliContext ctx = new DashboardIntelliContext(parameterTreeRootNode,gaSearchHandler.getChromosomeTree());
					gaPlugin.alterParameterTree(ctx);
					parameterTree = InfoConverter.node2ParameterTree(parameterTreeRootNode);
					dashboard.setOptimizationDirection(gaSearchHandler.getFitnessFunctionDirection());
					
				} else return false;
			}

			currentModelHandler.setParameters(parameterTree);
		}
		
		return true;
	}

	//----------------------------------------------------------------------------------------------------
	public Model saveConfiguration() throws IOException {
		final ObjectFactory factory = new ObjectFactory();
		
		final Model result = factory.createModel();
		result.setClazz(currentModelHandler.getModelClass().getName());
		
		if (tabbedPane.getSelectedIndex() == SINGLE_RUN_GUI_TABINDEX) {
			result.setRunStrategy(ModelType.SINGLE);
			
			final List<GeneralParameter> generalParameters = result.getGeneralParameterList();
			
			GeneralParameter gp = factory.createGeneralParameter();
			gp.setName(ParameterTreeUtils.NUMBER_OF_TURNS_XML_NAME);
			gp.setValue(numberOfTurnsField.getText());
			generalParameters.add(gp);
			
			gp = factory.createGeneralParameter();
			gp.setName(ParameterTreeUtils.NUMBER_OF_TIMESTEPS_TO_IGNORE_XML_NAME);
			gp.setValue(numberTimestepsIgnored.getText());
			generalParameters.add(gp);
			
			gp = factory.createGeneralParameter();
			gp.setName(ParameterTreeUtils.UPDATE_CHARTS_XML_NAME);
			gp.setValue(String.valueOf(onLineChartsCheckBox.isSelected()));
			generalParameters.add(gp);
			
			gp = factory.createGeneralParameter();
			gp.setName(ParameterTreeUtils.DISPLAY_ADVANCED_CHARTS_XML_NAME);
			gp.setValue(String.valueOf(advancedChartsCheckBox.isSelected()));
			generalParameters.add(gp);
			
			final Set<ParameterInfo> invalids = new HashSet<ParameterInfo>();
			
			final List<Parameter> parameterList = result.getParameterList();
			final List<SubmodelParameter> submodelParameterList = result.getSubmodelParameterList();
			
			@SuppressWarnings("rawtypes")
			final Enumeration firstLevelParameters = parameterValueComponentTree.children();
			saveSubTree(firstLevelParameters,parameterList,submodelParameterList,invalids);
		} else if (tabbedPane.getSelectedIndex() == PARAMSWEEP_GUI_TABINDEX) {
			result.setRunStrategy(ModelType.PARAMETER_SWEEP);
			
			//calculate the number of runs, which is the minimum of the number of runs in the parameter combination boxes
			int validMin = Integer.MAX_VALUE;
			for (final ParameterCombinationGUI pGUI : parameterTreeBranches) {
				final int run = Page_Parameters.calculateNumberOfRuns(pGUI.combinationRoot);
				if (run> 1 && run< validMin)
					validMin = run;
			}
			
			result.setNumberOfRuns(validMin);
			
			final List<GeneralParameter> generalParameters = result.getGeneralParameterList();
			
			GeneralParameter gp = factory.createGeneralParameter();
			gp.setName(ParameterTreeUtils.NUMBER_OF_TURNS_XML_NAME);
			gp.setValue(numberOfTurnsFieldPSW.getText());
			generalParameters.add(gp);
			
			gp = factory.createGeneralParameter();
			gp.setName(ParameterTreeUtils.NUMBER_OF_TIMESTEPS_TO_IGNORE_XML_NAME);
			gp.setValue(numberTimestepsIgnoredPSW.getText());
			generalParameters.add(gp);
			
			savePSParameterList(factory,result);
			
			for (int i = 0;i < parameterTreeBranches.size();++i) 
				savePSBranch(factory,result,parameterTreeBranches.get(i),i + 1);
		} else {
			result.setRunStrategy(ModelType.GA);
			gaSearchHandler.saveConfiguration(factory,result);
		}
		
		return result;
	}

	//----------------------------------------------------------------------------------------------------
	private void saveSubTree(@SuppressWarnings("rawtypes") final Enumeration children, final List<Parameter> parameterList,
							 final List<SubmodelParameter> submodelParameterList, final Set<ParameterInfo> invalids) throws IOException {
		
		final ObjectFactory factory = new ObjectFactory();
		while (children.hasMoreElements()) {
			final DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement();
			
			@SuppressWarnings("unchecked")
			final Pair<ParameterInfo,JComponent> userData = (Pair<ParameterInfo,JComponent>) node.getUserObject();
			final ParameterInfo parameterInfo = userData.getFirst();
			final JComponent valueContainer = userData.getSecond();
			
			Parameter parameter = null;
			SubmodelParameter submodelParameter = null;
			if (parameterInfo instanceof ISubmodelGUIInfo) {
				final ISubmodelGUIInfo sgi = (ISubmodelGUIInfo) parameterInfo;
				if (sgi.getParent() != null) {
					final DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) node.getParent();
					@SuppressWarnings("unchecked")
					final Pair<ParameterInfo,JComponent> parentUserData = (Pair<ParameterInfo,JComponent>) parentNode.getUserObject();
					final SubmodelInfo parentParameterInfo = (SubmodelInfo) parentUserData.getFirst();
					if (invalids.contains(parentParameterInfo) || !classEquals(parentParameterInfo.getActualType(),sgi.getParentValue())) {
						invalids.add(parameterInfo);
						continue;
					}
				}
			}
			
			if (parameterInfo instanceof SubmodelInfo) {
				submodelParameter = factory.createSubmodelParameter();
				submodelParameter.setName(parameterInfo.getName());
			} else {
				parameter = factory.createParameter();
				parameter.setName(parameterInfo.getName());
			}
			
			if (parameterInfo.isBoolean()){
				final JCheckBox checkBox = (JCheckBox) valueContainer;
				parameter.getContent().add(String.valueOf(checkBox.isSelected()));
			} else if (parameterInfo.isEnum()) {
				final JComboBox comboBox = (JComboBox) valueContainer;
				parameter.getContent().add(String.valueOf(comboBox.getSelectedItem()));
			} else if (parameterInfo instanceof MasonChooserParameterInfo) {
				final JComboBox comboBox = (JComboBox) valueContainer;
				parameter.getContent().add(String.valueOf(comboBox.getSelectedIndex()));
			} else if (parameterInfo instanceof SubmodelInfo) {
				final JComboBox comboBox = (JComboBox) ((JPanel)valueContainer).getComponent(0);
				final ClassElement selectedElement = (ClassElement) comboBox.getSelectedItem();
				
				if (selectedElement.clazz == null)
					throw new IOException("No type is selected for parameter " + parameterInfo.getName().replaceAll("([A-Z])", " $1") + ".");
				
				submodelParameter.setType(selectedElement.clazz.getName());
				saveSubTree(node.children(),submodelParameter.getParameterList(),submodelParameter.getSubmodelParameterList(),invalids);
			} else if (parameterInfo.isFile()) {
				final JTextField textField = (JTextField) valueContainer.getComponent(0);
				parameter.getContent().add(textField.getToolTipText());
			} else if (parameterInfo instanceof MasonIntervalParameterInfo) {
				final JTextField textField = (JTextField) valueContainer.getComponent(0);
				parameter.getContent().add(textField.getText().trim());
			} else {
				final JTextField textField = (JTextField) valueContainer;
				String text = String.valueOf(ParameterInfo.getValue(textField.getText(),parameterInfo.getType()));
				if ("String".equals(parameterInfo.getType()) && parameterInfo.getValue() == null)
					text = textField.getText().trim();
				parameter.getContent().add(text);
			}
			
			if (parameter != null)
				parameterList.add(parameter);
			else if (submodelParameter != null)
				submodelParameterList.add(submodelParameter);
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	private void savePSParameterList(final ObjectFactory factory, final Model model) {
		final DefaultListModel listModel = (DefaultListModel) parameterList.getModel();
		
		if (!listModel.isEmpty()) {
			for (int i = 0;i < listModel.getSize();++i) {
				final AvailableParameter availableParameter = (AvailableParameter) listModel.get(i);
				
				final DefaultParameter defaultParameter = factory.createDefaultParameter();
				defaultParameter.setName(availableParameter.info.getName());
				model.getDefaultParameterList().add(defaultParameter);
			}
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	private void savePSBranch(final ObjectFactory factory, final Model model, final ParameterCombinationGUI combinationGUI, final int position) {
		final Combination combination = factory.createCombination();
		combination.setPosition(BigInteger.valueOf(position));
		model.getCombination().add(combination);
		
		int pPosition = 1;
		@SuppressWarnings("rawtypes")
		final Enumeration paramNodes = combinationGUI.combinationRoot.children();
		while (paramNodes.hasMoreElements()) {
			final DefaultMutableTreeNode node = (DefaultMutableTreeNode) paramNodes.nextElement();
			savePSParameter(node,factory,combination,pPosition++);
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	private void savePSParameter(final DefaultMutableTreeNode node, final ObjectFactory factory, final Object parent, final int position) {
		final ParameterInATree userObj = (ParameterInATree) node.getUserObject();
		final ParameterInfo info = userObj.info;
		
		if (info instanceof SubmodelInfo) {
			final SubmodelInfo sInfo = (SubmodelInfo) info;
			
			final SubmodelParameter parameter = factory.createSubmodelParameter();
			parameter.setName(info.getName());
			parameter.setType(sInfo.getActualType() == null ? "null" : sInfo.getActualType().getName());
			parameter.setPosition(BigInteger.valueOf(position));
			
			if (parent instanceof Combination) {
				final Combination combination = (Combination) parent;
				combination.getSubmodelParameterList().add(parameter);
			} else if (parent instanceof SubmodelParameter) {
				final SubmodelParameter submodelParameter = (SubmodelParameter) parent;
				submodelParameter.getSubmodelParameterList().add(parameter);
			}
			
			if (node.getChildCount() > 0) {
				@SuppressWarnings("rawtypes")
				final Enumeration childNodes = node.children();
				int childPosition = 1;
				while (childNodes.hasMoreElements()) {
					final DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) childNodes.nextElement();
					savePSParameter(childNode,factory,parameter,childPosition++);
 				}
			}
		} else {
			final Parameter parameter = factory.createParameter();
			parameter.setName(info.getName());
			parameter.setPosition(BigInteger.valueOf(position));
			
			switch (info.getDefinitionType()) {
			case ParameterInfo.CONST_DEF:	
				parameter.setParameterType(ParameterType.CONSTANT);
				parameter.getContent().add(info.getValue().toString());
				break;
				
			case ParameterInfo.LIST_DEF:
				parameter.setParameterType(ParameterType.LIST);
				savePSListParameter(info,parameter,factory);
				break;
			
			case ParameterInfo.INCR_DEF:
				parameter.setParameterType(ParameterType.INCREMENT);
				savePSIncrementParameter(info,parameter,factory);
				break;
			}
			
			if (parent instanceof Combination) {
				final Combination combination = (Combination) parent;
				combination.getParameterList().add(parameter);
			} else if (parent instanceof SubmodelParameter) {
				final SubmodelParameter submodelParameter = (SubmodelParameter) parent;
				submodelParameter.getParameterList().add(parameter);
			}
		}
	}

	//----------------------------------------------------------------------------------------------------
	private void savePSListParameter(final ParameterInfo info, final Parameter parameter, final ObjectFactory factory) {
		for (final Object listElement : info.getValues()) {
			final JAXBElement<String> element = factory.createParameterParameterValue(listElement.toString());
			parameter.getContent().add(element);
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	private void savePSIncrementParameter(final ParameterInfo info, final Parameter parameter, final ObjectFactory factory) {
		JAXBElement<String> element = factory.createParameterStartValue(info.getStartValue().toString());
		parameter.getContent().add(element);
		element = factory.createParameterEndValue(info.getEndValue().toString());
		parameter.getContent().add(element);
		element = factory.createParameterStepValue(info.getStep().toString());
		parameter.getContent().add(element);
	}

	//----------------------------------------------------------------------------------------------------
	public void loadConfiguration(final Model model) {
		try {
			currentModelHandler = dashboard.getModelHandler();
			singleRunParametersPanel.removeAll();
			
			parameterValueComponentTree = new DefaultMutableTreeNode();
			possibleTypesCache.clear();
			batchParameters = currentModelHandler.getParameters();
			
			final ModelType runStrategy = model.getRunStrategy();

			if (ModelType.SINGLE == runStrategy)
				fillParameterValueComponentTree(model);
				
			final List<ParameterInfo> modelParameters = createAndDisplayAParameterPanel(
			   batchParameters, "Model parameters", null, true, currentModelHandler);

			parametersScrollPane.setViewportView(singleRunParametersPanel);
			singleRunParametersPanel.revalidate();
			

			if (ModelType.SINGLE == runStrategy) {
				tabbedPane.setSelectedIndex(SINGLE_RUN_GUI_TABINDEX);
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						numberOfTurnsField.grabFocus();
					}
				});
			}
				
			// initialize paramsweep panel
			Collections.sort(modelParameters);
			enableDisableSettings(false);
			modifyButton.setEnabled(false);
			resetParamsweepGUI();
			
			if (ModelType.PARAMETER_SWEEP == runStrategy) {
				fillParameterSweepPage(model);
				tabbedPane.setSelectedIndex(PARAMSWEEP_GUI_TABINDEX);
			} else 
				createDefaultParameterList(modelParameters);
			
			updateNumberOfRuns();
			
			// initialize the GA seach panel
			gaSearchHandler.init(currentModelHandler);
			gaSearchHandler.removeAllFitnessFunctions();
			final List<RecordableInfo> recordables = dashboard.getModelHandler().getRecorders().get(0).getRecordables();
			for (final RecordableInfo recordableInfo : recordables) {
				if (gaSearchHandler.canBeFitnessFunction(recordableInfo))
					gaSearchHandler.addFitnessFunction(recordableInfo);
			}
			
			if (ModelType.GA == runStrategy) {
				gaSearchHandler.loadConfiguration(model,modelParameters);
				tabbedPane.setSelectedIndex(GASEARCH_GUI_TABINDEX);
//				gaSearchPanel.setSelectedFitnessFunction(gaSearchHandler); this is handled by gaSearchPanel.reset()
			}
			
			gaSearchPanel.reset(gaSearchHandler);
		} catch (final ModelInformationException e) {
			JOptionPane.showMessageDialog(wizard, new JLabel(e.getMessage()), "Error while analyizing model and/or configuration file", JOptionPane.ERROR_MESSAGE);
			e.printStackTrace();
		} finally {
			((CardLayout)container.getLayout()).show(container, PARAMETERS_PANEL_ID);
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	private void fillParameterValueComponentTree(final Model model) throws ModelInformationException {
		final List<GeneralParameter> generalParameters = model.getGeneralParameterList();
		for (final GeneralParameter gp : generalParameters) {
			if (NUMBER_OF_TURNS_LABEL_TEXT.equals(gp.getName()))
				numberOfTurnsField.setText(gp.getValue());
			else if (NUMBER_OF_TIMESTEPS_TO_IGNORE_LABEL_TEXT.equals(gp.getName()))
				numberTimestepsIgnored.setText(gp.getValue());
			else if (UPDATE_CHARTS_LABEL_TEXT.equals(gp.getName())) {
				final boolean selected = Boolean.parseBoolean(gp.getValue());
				onLineChartsCheckBox.setSelected(selected);
			} else if (DISPLAY_ADVANCED_CHARTS_LABEL_TEXT.equals(gp.getName())) {
				final boolean selected = Boolean.parseBoolean(gp.getValue());
				advancedChartsCheckBox.setSelected(selected);
			}
		}
		
		final DefaultMutableTreeNode infoValueTree = ParameterTreeUtils.loadSingleRunParameterIntoInfoValueTree(model,batchParameters,currentModelHandler);
		parameterValueComponentTree = convertInfoValueTreeToInfoComponentTree(infoValueTree);
	}
	
	//----------------------------------------------------------------------------------------------------
	private DefaultMutableTreeNode convertInfoValueTreeToInfoComponentTree(DefaultMutableTreeNode infoValueTree) throws ModelInformationException {
		@SuppressWarnings("rawtypes")
		final Enumeration nodes = infoValueTree.breadthFirstEnumeration();
		nodes.nextElement(); // root
		
		while (nodes.hasMoreElements()) {
			final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement();
			if (node.getUserObject() != null) {
				@SuppressWarnings("unchecked")
				final Pair<ParameterInfo,String> userObj = (Pair<ParameterInfo,String>) node.getUserObject();
				final JComponent component = convertStringToComponent(userObj.getKey(),userObj.getValue());
				final Pair<ParameterInfo,JComponent> newUserObj = new Pair<ParameterInfo,JComponent>(userObj.getKey(),component);
				node.setUserObject(newUserObj);
			}
		}
		
		return infoValueTree;
	}

	//----------------------------------------------------------------------------------------------------
	private JComponent convertStringToComponent(final ParameterInfo info, final String value) throws ModelInformationException {
		if (info instanceof SubmodelInfo)
			return initializeJComponentForSubmodelParameter(value,(SubmodelInfo)info);
		
		return initializeJComponentForParameter(value,info);
	}

	//----------------------------------------------------------------------------------------------------
	@SuppressWarnings("unchecked")
	private JComponent initializeJComponentForParameter(final String strValue, final ParameterInfo info) throws ModelInformationException {
		JComponent field = null;
		
		if (info.isBoolean()){
			field = new JCheckBox();
			boolean value = Boolean.parseBoolean(strValue); 
			((JCheckBox)field).setSelected(value);
		} else if (info.isEnum() || info instanceof MasonChooserParameterInfo) {
			Object[] elements = null;
			if (info.isEnum()){
				final Class<Enum<?>> type = (Class<Enum<?>>) info.getJavaType();
				elements = type.getEnumConstants();
			} else {
				final MasonChooserParameterInfo chooserInfo = (MasonChooserParameterInfo) info;
				elements = chooserInfo.getValidStrings();
			}
			final JComboBox list = new JComboBox(elements);

			if (info.isEnum()) {
				try {
					@SuppressWarnings("rawtypes")
					final Object value = Enum.valueOf((Class<? extends Enum>)info.getJavaType(),strValue);
					list.setSelectedItem(value);
				} catch (final IllegalArgumentException e) {
					throw new ModelInformationException(e.getMessage() + " for parameter: " + info.getName() + ".");
				}
			} else {
				try {
					final int value = Integer.parseInt(strValue);
					list.setSelectedIndex(value);
				} catch (final NumberFormatException e) {
					throw new ModelInformationException("Invalid value for parameter " + info.getName() + " (not a number).");
				}
			}
			field = list;
		} else if (info.isFile()) {
			field = new JPanel();
			final JTextField textField = new JTextField();
			
			if (!strValue.isEmpty()) {
				final File file = new File(strValue);
				textField.setText(file.getName());
				textField.setToolTipText(file.getAbsolutePath());
			}
			
			field.add(textField);
		} else if (info instanceof MasonIntervalParameterInfo) {
			field = new JPanel();
			final JTextField textField = new JTextField(strValue);
			field.add(textField);
		} else {
			field = new JTextField(strValue);
		}
		
		return field;
	}
	
	//----------------------------------------------------------------------------------------------------
	private JComponent initializeJComponentForSubmodelParameter(final String type, final SubmodelInfo submodelInfo) throws ModelInformationException {
		try {
			final Class<?> clazz = Class.forName(type,true,currentModelHandler.getCustomClassLoader());
			final Object value = new ClassElement(clazz, null);
			submodelInfo.setActualType(clazz, null);
			final Object[] elements = new Object[] { value }; 
			final JComboBox list = new JComboBox(elements);
			list.setSelectedIndex(0);
			JPanel panel = new JPanel();
			panel.add(list);
			
			return panel;
		} catch (final ClassNotFoundException e) {
			throw new ModelInformationException("Invalid actual type " + type + " for submodel parameter: " + submodelInfo.getName(),e);
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	private void fillParameterSweepPage(final Model model) throws ModelInformationException {
		final List<GeneralParameter> generalParameters = model.getGeneralParameterList();
		for (final GeneralParameter gp : generalParameters) {
			if (NUMBER_OF_TURNS_LABEL_TEXT.equals(gp.getName()))
				numberOfTurnsFieldPSW.setText(gp.getValue());
			else if (NUMBER_OF_TIMESTEPS_TO_IGNORE_LABEL_TEXT.equals(gp.getName()))
				numberTimestepsIgnoredPSW.setText(gp.getValue());
		}
		
		final DefaultListModel listModel = new DefaultListModel();
		final List<DefaultParameter> defaultParameters = model.getDefaultParameterList();
		ParameterTreeUtils.loadPSDefaultParameters(listModel,defaultParameters,batchParameters, currentModelHandler.getModelClass());
		parameterList.setModel(listModel);
		
		// creating combination boxes
		for (int i = 0;i < model.getCombination().size() - 1;addBox(),++i);
		
		final List<Combination> sortedCombinations = new ArrayList<Combination>(model.getCombination());
		Collections.sort(sortedCombinations,new Comparator<Combination>(){
			public int compare(final Combination o1, final Combination o2) {
				return o1.getPosition().compareTo(o2.getPosition());
			}
		});
		
		for (int i = 0;i < sortedCombinations.size();++i) {
			final ParameterCombinationGUI pGUI = parameterTreeBranches.get(i);
			final DefaultTreeModel treeModel = (DefaultTreeModel) pGUI.tree.getModel();
			final DefaultMutableTreeNode combinationRoot = pGUI.combinationRoot;
			ParameterTreeUtils.loadAPSCombinationTree(treeModel,combinationRoot,batchParameters,currentModelHandler,sortedCombinations.get(i));
			
			for (int j = 0;j < pGUI.tree.getRowCount();++j) 
		         pGUI.tree.expandRow(j);
		}
	}

	//----------------------------------------------------------------------------------------------------
	private void dumpParameterTree(final ParameterNode rootNode) {
		dumpParameterTreeBranch(rootNode, "");
	}
	
	//----------------------------------------------------------------------------------------------------
	private void dumpParameterTreeBranch(final ParameterNode node, final String prefix){
		@SuppressWarnings("unchecked")
		final Enumeration<ParameterNode> children = node.children();
		
		while (children.hasMoreElements()) {
			final ParameterNode child = children.nextElement();
			final ai.aitia.meme.paramsweep.batch.param.AbstractParameterInfo<?> info = (ai.aitia.meme.paramsweep.batch.param.AbstractParameterInfo<?>) child.getUserObject();
			if (info instanceof IncrementalParameterInfo<?>) {
				final IncrementalParameterInfo<?> incrementalInfo = (IncrementalParameterInfo<?>) info;
				log.debug(prefix + info.getName() + ": start = " + incrementalInfo.getStart() + "; end = " + incrementalInfo.getEnd() + "; increment = " + incrementalInfo.getIncrement() + "; run = " + incrementalInfo.getRunNumber());
			} else if (info instanceof ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>) {
				final ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?> simpleInfo = (ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>) info;
				log.debug(prefix + info.getName() + ": " + simpleInfo.getValues() + "; run = " + simpleInfo.getRunNumber());
			} else {
				throw new IllegalStateException("Trying to dump unknown parameterinfo: " + info);
			}
			
			if (info.getMultiplicity() > 1) {
				dumpParameterTreeBranch(child, prefix + "\t");
			}
		}
	}

	//----------------------------------------------------------------------------------------------------
	/** {@inheritDoc} 
	 */
	@Override
	public void onPageChange(final boolean show) {
		if (show){
			dashboard.getSaveConfigMenuItem().setEnabled(true);
			if (currentModelHandler == null || !currentModelHandler.equals(dashboard.getModelHandler())){
				((CardLayout)container.getLayout()).show(container, LOADING_MODEL_ID);
			
				SwingUtilities.invokeLater(new Runnable() {
					
					@Override
					public void run() {
						try {
							currentModelHandler = dashboard.getModelHandler();
							
							breadcrumb.setRoot(
							   currentModelHandler.getModelClassSimpleName().replaceAll("([A-Z])", " $1"));
							Style.apply(breadcrumb, dashboard.getCssStyle());
							parameterValueComponentTree = new DefaultMutableTreeNode();
							possibleTypesCache.clear();
							singleRunParametersPanel.removeAll();
							batchParameters = currentModelHandler.getParameters();
							final List<ParameterInfo> modelParameters = createAndDisplayAParameterPanel(
							   batchParameters,"Model parameters",null, true,
							   currentModelHandler
							   );

							//parametersScrollPane.setViewportView(singleRunParametersPanel);

							singleRunParametersPanel.revalidate();

							// initialize paramsweep panel
							Collections.sort(modelParameters);
							createDefaultParameterList(modelParameters);
							enableDisableSettings(false);
							modifyButton.setEnabled(false);
							updateNumberOfRuns();
							resetParamsweepGUI();

							// initialize the GA seach panel
							gaSearchHandler.init(currentModelHandler);
							gaSearchPanel.reset(gaSearchHandler);
							gaSearchHandler.removeAllFitnessFunctions();
							final List<RecordableInfo> recordables = dashboard.getModelHandler().getRecorders().get(0).getRecordables();
							for (final RecordableInfo recordableInfo : recordables) {
								if (gaSearchHandler.canBeFitnessFunction(recordableInfo))
									gaSearchHandler.addFitnessFunction(recordableInfo);
							}

							gaSearchHandler.removeAllParameters();
							for (final ParameterInfo parameterInfo : modelParameters) 
								gaSearchHandler.addParameter(new ParameterOrGene(parameterInfo));
						} catch (final ModelInformationException e) {
							JOptionPane.showMessageDialog(wizard, new JLabel(e.getMessage()), "Error while analyizing model", JOptionPane.ERROR_MESSAGE);
							e.printStackTrace();
						} finally {
							((CardLayout)container.getLayout()).show(container, PARAMETERS_PANEL_ID);
						}
					}
				});
			}
		} else { // this should only run when moving onto Page_Run
		}

	}

	//----------------------------------------------------------------------------------------------------
	@Override
	public String getTitle() {
		return TITLE;
	}

   //-----------------------------------------------------------------------------------
   
   private final static class ParameterMetaData implements Comparable<ParameterMetaData> {
      String
         banner = "",
         verboseDescription = "",
         fieldName = "",
         imageFileName = "";
      double
         layoutOrder = Double.MIN_VALUE;
      ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>
         parameter;
      @Override
      public int compareTo(final ParameterMetaData other) {
         if(layoutOrder != other.layoutOrder)
            return Double.compare(layoutOrder, other.layoutOrder);
         return parameter.getName().compareTo(other.parameter.getName());
      }
      
      static void createAndRegisterUnknown(
         final String expecteFieldName,
         final ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?> paramter,
         final List<ParameterMetaData> collection
         ) {
         System.err.println(
            "Dashboard: no field with name " + expecteFieldName + " is present.");
         System.err.flush();
         final ParameterMetaData
            datum = new ParameterMetaData();
         datum.parameter = paramter;
         datum.fieldName = paramter.getName().replaceAll("([A-Z])", " $1");
         datum.imageFileName = "";
         collection.add(datum);
      }
   }
   
   private void appendMinimumWidthHintToPresentation(
      final DefaultFormBuilder formBuilder,
      final int widthInPt
      ) {
      formBuilder.append(
         new JLabel(
         "<html><div style=\"margin: 0pt; display: block; width:" + widthInPt 
       + "pt; height:0pt\"></div></html>") { 
            private static final long serialVersionUID = -722208290456978697L;
         }, 3);
   }
   
   private void appendTextToPresentation(
      DefaultFormBuilder formBuilder,
      final String text
      ) {
      if(text == null || text.isEmpty()) return;
      /*
       * Subclass JLabel to lie about the with of the component. We understate the preferred 
       * width to avoid that this component influences the width of the columns. It is unclear 
       * why we need to use colspan = 3 here.
       */
      formBuilder.append(
         new JLabel(
            "<html><div style=\"margin-bottom: 8pt; margin-left: 4pt; margin-top: 12pt;"
          + "line-height:1.5; color:#555555\"><i>" + text.replace("\n", "<br/>") 
          + "</i></div></html>"
          ) {
            private static final long serialVersionUID = 1L;
            
            @Override
            public Dimension getPreferredSize() {
               Dimension preferredSize = super.getPreferredSize();
               return new Dimension(10, preferredSize.height);
            }
         }, 3);
   }
   
   private void appendImageToPresentation(
      DefaultFormBuilder formBuilder,
      final String imageFilename
      ) {
      if(imageFilename == null || imageFilename.isEmpty()) return;
      ImageIcon
         icon = null;
      try {
         final ClassLoader
            classLoader = Thread.currentThread().getContextClassLoader();
         final InputStream
            imageStream = classLoader.getResourceAsStream(imageFilename);
         final Image
            image = ImageIO.read(imageStream);
         icon = new ImageIcon(image);
      } catch (final IOException e) {
         icon = new ImageIcon(imageFilename);
      }
      
      final JLabel 
         component = new JLabel(
            "<html><div style=\"margin: 8pt\"></div></html>"
            );
      component.setIcon(icon);
      formBuilder.append(component, 3);
   }
   
   private void appendHeaderTextToPresentation(
      DefaultFormBuilder formBuilder,
      final String text
      ) {
      if(text == null || text.isEmpty()) return;
      
      formBuilder.append(
         new JLabel(
            "<html><div style=\"margin-bottom: 8pt; margin-left: 4pt; margin-top: 12pt;"
          + " display: block; color:#666666; display: block\"><i>" + text.replace("\n", "<br/>") 
          + "</i></div></html>"
          ) {
          private static final long serialVersionUID = 1L;
          
          @Override
          public Dimension getPreferredSize() {
             Dimension preferredSize = super
                .getPreferredSize();
             return new Dimension(
                10,
                preferredSize.height);
          }
       }, 3);
   }
   
   private void appendBannerToPresentation(
      DefaultFormBuilder formBuilder,
      final String text
      ) {
      if(text == null || text.isEmpty()) return;
      formBuilder.appendSeparator(text);
   }
   
   private void appendVerticalSpaceToPresentation(DefaultFormBuilder formBuilder) {
      formBuilder.append("", new JPanel());
   }
   
   private void appendCheckBoxFieldToPresentation(
      DefaultFormBuilder formBuilder,
      final String fieldText,
      final JCheckBox checkBox
      ) {
      formBuilder.append(
         "<html><div style=\"margin-bottom: 4pt; margin-top: 6pt; margin-left: 4pt\">"
       + fieldText + "</div></html>", checkBox
         );
   }
   
   @SuppressWarnings("unchecked")
   private List<ParameterInfo> createAndDisplayAParameterPanel(
      final List<ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>> batchParameters,
      final String title,
      final SubmodelInfo parent,
      final boolean submodelSelectionWithoutNotify,
      final IModelHandler currentModelHandler)
      {
      final List<ParameterMetaData>
         metadata = new LinkedList<ParameterMetaData>(),
         unknownFields = new ArrayList<ParameterMetaData>();
      for(final ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?> record : batchParameters) {
         final String
            parameterName = record.getName(),
            fieldName = StringUtils.uncapitalize(parameterName);
         Class<?>
            modelComponentType = parent == null ?
               currentModelHandler.getModelClass() : parent.getActualType();
         while(true) {
            try {
               final Field
                  field = modelComponentType.getDeclaredField(fieldName);
               final ParameterMetaData
                  datum = new ParameterMetaData();
               for(final Annotation element : field.getAnnotations()) {
                  if(element.annotationType().getName() != Layout.class.getName())     // Proxies
                     continue;
                  final Class<? extends Annotation>
                     type = element.annotationType();
                  datum.verboseDescription = (String)
                     type.getMethod("VerboseDescription").invoke(element);
                  datum.banner = (String)
                     type.getMethod("Title").invoke(element);
                  datum.fieldName = (String)
                     " " + type.getMethod("FieldName").invoke(element);
                  datum.imageFileName = (String)
                     type.getMethod("Image").invoke(element);
                  datum.layoutOrder = (Double) 
                     type.getMethod("Order").invoke(element);
               }
               datum.parameter = record;
               if(datum.fieldName.trim().isEmpty())
                  datum.fieldName = parameterName.replaceAll("([A-Z])", " $1");
               metadata.add(datum);
               break;
            } catch (final SecurityException e) {
            } catch (final NoSuchFieldException e) {
            } catch (final IllegalArgumentException e) {
            } catch (final IllegalAccessException e) {
            } catch (final InvocationTargetException e) {
            } catch (final NoSuchMethodException e) {
            }
            modelComponentType = modelComponentType.getSuperclass();
            if(modelComponentType == null) {
               ParameterMetaData.createAndRegisterUnknown(fieldName, record, unknownFields);
               break;
            }
         }
      }
      Collections.sort(metadata);
      for(int i = unknownFields.size() - 1; i>= 0; --i)
         metadata.add(0, unknownFields.get(i));
      
      // initialize single run form
      final DefaultFormBuilder formBuilder = FormsUtils.build("p ~ p:g", "");
      appendMinimumWidthHintToPresentation(formBuilder, 550);
      
      if (parent == null) {
         SwingUtilities.invokeLater(new Runnable() {
            
            @Override
            public void run() {
               numberOfTurnsField.grabFocus();
            }
         });
         
         appendBannerToPresentation(formBuilder, "General Parameters");
         appendTextToPresentation(formBuilder,
            "Global parameters affecting the entire simulation");
         
         formBuilder.append(NUMBER_OF_TURNS_LABEL_TEXT, numberOfTurnsField);
         formBuilder.append(NUMBER_OF_TIMESTEPS_TO_IGNORE_LABEL_TEXT, numberTimestepsIgnored);
         
         appendCheckBoxFieldToPresentation(
            formBuilder, UPDATE_CHARTS_LABEL_TEXT, onLineChartsCheckBox);
         appendCheckBoxFieldToPresentation(
            formBuilder, DISPLAY_ADVANCED_CHARTS_LABEL_TEXT, advancedChartsCheckBox);
      } 
      
      appendBannerToPresentation(formBuilder, title);
      
      final DefaultMutableTreeNode
         parentNode = (parent == null) ?
            parameterValueComponentTree : findParameterInfoNode(parent, false);
      
      final List<ParameterInfo> info = new ArrayList<ParameterInfo>();
      
      // Search for a @ConfigurationComponent annotation
      {
         String
            headerText = "",
            imagePath = "";
         final Class<?> parentType =
            parent == null ?
               currentModelHandler.getModelClass() :
               parent.getActualType();
         for(final Annotation element : parentType.getAnnotations()) {               // Proxies
            if(element.annotationType().getName() != ConfigurationComponent.class.getName())
               continue;
            boolean
               doBreak = false;
            try{
               try {
                  headerText =
                     (String) element.annotationType().getMethod("Description").invoke(element);
                  if(headerText.startsWith("#")) {
                     headerText = (String) parent.getActualType().getMethod(
                        headerText.substring(1)).invoke(parent.getInstance());
                  }
                  doBreak = true;
               } catch (IllegalArgumentException e) {
               } catch (SecurityException e) {
               } catch (IllegalAccessException e) {
               } catch (InvocationTargetException e) {
               } catch (NoSuchMethodException e) {
               }
            }
            catch(final Exception e) {
            }
            try {
               imagePath =
                  (String) element.annotationType().getMethod("ImagePath").invoke(element);
               doBreak = true;
            } catch (IllegalArgumentException e) {
            } catch (SecurityException e) {
            } catch (IllegalAccessException e) {
            } catch (InvocationTargetException e) {
            } catch (NoSuchMethodException e) {
            }
            if(doBreak)
               break;
         }
         if(!headerText.isEmpty())
            appendHeaderTextToPresentation(formBuilder, headerText);
         if(!imagePath.isEmpty())
            appendImageToPresentation(formBuilder, imagePath);
      }
      
      if(metadata.isEmpty()) {
         // No fields to display.
         appendTextToPresentation(formBuilder, "No configuration is required for this module.");
      }
      else {
    	  for(final ParameterMetaData record : metadata) {
    		  final ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>
    		  batchParameterInfo = record.parameter;

    		  if(!record.banner.isEmpty())
    			  appendBannerToPresentation(formBuilder, record.banner);
    		  if(!record.imageFileName.isEmpty())
    			  appendImageToPresentation(formBuilder, record.imageFileName);
    		  appendTextToPresentation(formBuilder, record.verboseDescription);

    		  final ParameterInfo parameterInfo = InfoConverter.parameterInfo2ParameterInfo(batchParameterInfo);
    		  if (parent != null && parameterInfo instanceof ISubmodelGUIInfo) {
//					sgi.setParentValue(parent.getActualType());
    		  }

    		  final JComponent field;
    		  final DefaultMutableTreeNode oldNode = findParameterInfoNode(parameterInfo,true);
    		  Pair<ParameterInfo,JComponent> userData = null;
    		  JComponent oldField = null;
    		  if (oldNode != null) {
    			  userData = (Pair<ParameterInfo,JComponent>) oldNode.getUserObject();
    			  oldField = userData.getSecond();
    		  }

    		  if (parameterInfo.isBoolean()) {
    			  field = new JCheckBox();
    			  boolean value = oldField != null ? ((JCheckBox)oldField).isSelected()
    					  : ((Boolean)batchParameterInfo.getDefaultValue()).booleanValue(); 
    			  ((JCheckBox)field).setSelected(value);
    		  } else if (parameterInfo.isEnum() || parameterInfo instanceof MasonChooserParameterInfo) {
    			  Object[] elements = null;
    			  if (parameterInfo.isEnum()) {
    				  final Class<Enum<?>> type = (Class<Enum<?>>) parameterInfo.getJavaType();
    				  elements = type.getEnumConstants();
    			  } else {
    				  final MasonChooserParameterInfo chooserInfo = (MasonChooserParameterInfo)parameterInfo;
    				  elements = chooserInfo.getValidStrings();
    			  }
    			  final JComboBox list = new JComboBox(elements);

    			  if (parameterInfo.isEnum()) {
    				  final Object value = oldField != null ? ((JComboBox)oldField).getSelectedItem()
    						  : parameterInfo.getValue();
    				  list.setSelectedItem(value);
    			  } else {
    				  final int value = oldField != null ? ((JComboBox)oldField).getSelectedIndex()
    						  : (Integer) parameterInfo.getValue();
    				  list.setSelectedIndex(value);
    			  }

    			  field = list;
    		  } else if (parameterInfo instanceof SubmodelInfo) {
    			  final SubmodelInfo submodelInfo = (SubmodelInfo) parameterInfo;
    			  final Object[] elements = new Object[] { "Loading class information..." }; 
    			  final JComboBox list = new JComboBox(elements);
    			  //				field = list;

    			  final Object value = oldField != null ? ((JComboBox)((JPanel)oldField).getComponent(0)).getSelectedItem()
    					  : new ClassElement(submodelInfo.getActualType(), null);

    			  new ClassCollector(this,list,submodelInfo,value,submodelSelectionWithoutNotify).execute();


    			  final JButton rightButton = new JButton();
    			  rightButton.setOpaque(false);
    			  rightButton.setRolloverEnabled(true);
    			  rightButton.setIcon(SHOW_SUBMODEL_ICON);
    			  rightButton.setRolloverIcon(SHOW_SUBMODEL_ICON_RO);
    			  rightButton.setDisabledIcon(SHOW_SUBMODEL_ICON_DIS);
    			  rightButton.setBorder(null);
    			  rightButton.setToolTipText("Display submodel parameters");
    			  rightButton.setActionCommand(ACTIONCOMMAND_SHOW_SUBMODEL);
    			  rightButton.addActionListener(new ActionListener() {

    				  @Override
    				  public void actionPerformed(ActionEvent arg0) {
    					  if (parameterInfo instanceof SubmodelInfo) {
    						  SubmodelInfo submodelInfo = (SubmodelInfo) parameterInfo;
    						  int level = 0;

    						  showHideSubparameters(list, submodelInfo);

    						  List<String> components = new ArrayList<String>();
    						  components.add(submodelInfo.getName());
    						  while (submodelInfo.getParent() != null){
    							  submodelInfo = submodelInfo.getParent();
    							  components.add(submodelInfo.getName());
    							  level++;
    						  }
    						  Collections.reverse(components);
    						  final String[]
    								  breadcrumbText = components.toArray(new String[components.size()]);
    						  for(int i = 0; i< breadcrumbText.length; ++i)
    							  breadcrumbText[i] = breadcrumbText[i].replaceAll("([A-Z])", " $1");
    						  breadcrumb.setPath(
    								  currentModelHandler.getModelClassSimpleName().replaceAll("([A-Z])", " $1"),
    								  breadcrumbText
    								  );
    						  Style.apply(breadcrumb, dashboard.getCssStyle());

    						  // reset all buttons that are nested deeper than this to default color
    						  for (int i = submodelButtons.size() - 1; i >= level ; i--) {
    							  JButton button = submodelButtons.get(i);
    							  button.setIcon(SHOW_SUBMODEL_ICON);
    							  submodelButtons.remove(i);
    						  }

    						  rightButton.setIcon(SHOW_SUBMODEL_ICON_RO);
    						  submodelButtons.add(rightButton);
    					  }
    				  }
    			  });

    			  field = new JPanel(new BorderLayout());
    			  field.add(list, BorderLayout.CENTER);
    			  field.add(rightButton, BorderLayout.EAST);
    		  } else if (File.class.isAssignableFrom(parameterInfo.getJavaType())){
    			  field = new JPanel(new BorderLayout());

    			  String oldName = "";
    			  String oldPath = "";
    			  if (oldField != null) {
    				  final JTextField oldTextField = (JTextField) oldField.getComponent(0);
    				  oldName = oldTextField.getText();
    				  oldPath = oldTextField.getToolTipText();
    			  } else if (parameterInfo.getValue() != null) {
    				  final File file = (File) parameterInfo.getValue();
    				  oldName = file.getName();
    				  oldPath = file.getAbsolutePath();
    			  }

    			  final JTextField textField = new JTextField(oldName);
    			  textField.setToolTipText(oldPath);
    			  textField.setInputVerifier(new InputVerifier() {

    				  @Override
    				  public boolean verify(final JComponent input) {
    					  final JTextField inputField = (JTextField) input;
    					  if (inputField.getText() == null || inputField.getText().isEmpty()) {
    						  final File file = new File("");
    						  inputField.setToolTipText(file.getAbsolutePath());
    						  hideError();
    						  return true;
    					  }

    					  final File oldFile = new File(inputField.getToolTipText());
    					  if (oldFile.exists() && oldFile.getName().equals(inputField.getText().trim())) {
    						  hideError();
    						  return true;
    					  }

    					  inputField.setToolTipText("");
    					  final File file = new File(inputField.getText().trim());
    					  if (file.exists()) {
    						  inputField.setToolTipText(file.getAbsolutePath());
    						  inputField.setText(file.getName());
    						  hideError();
    						  return true;
    					  } else {
    						  final PopupFactory popupFactory = PopupFactory.getSharedInstance();
    						  final Point locationOnScreen = inputField.getLocationOnScreen();
    						  final JLabel message = new JLabel("Please specify an existing file!");
    						  message.setBorder(new LineBorder(Color.RED, 2, true));
    						  if (errorPopup != null)
    							  errorPopup.hide();
    						  errorPopup = popupFactory.getPopup(inputField,message,locationOnScreen.x - 10,locationOnScreen.y - 30);
    						  errorPopup.show();
    						  return false;
    					  }
    				  }
    			  });

    			  final JButton browseButton = new JButton(BROWSE_BUTTON_TEXT);
    			  browseButton.addActionListener(new ActionListener() {
    				  @Override
    				  public void actionPerformed(ActionEvent e) {
    					  final JFileChooser fileDialog = new JFileChooser(!"".equals(textField.getToolTipText()) ? textField.getToolTipText() : currentDirectory);
    					  if (!"".equals(textField.getToolTipText()))
    						  fileDialog.setSelectedFile(new File(textField.getToolTipText()));
    					  int dialogResult = fileDialog.showOpenDialog(dashboard);
    					  if (dialogResult == JFileChooser.APPROVE_OPTION) {
    						  final File selectedFile = fileDialog.getSelectedFile();
    						  if (selectedFile != null) {
    							  currentDirectory = selectedFile.getAbsoluteFile().getParent();
    							  textField.setText(selectedFile.getName());
    							  textField.setToolTipText(selectedFile.getAbsolutePath());
    						  }
    					  }
    				  }
    			  });

    			  field.add(textField,BorderLayout.CENTER);
    			  field.add(browseButton,BorderLayout.EAST);
    		  } else if (parameterInfo instanceof MasonIntervalParameterInfo) {
    			  final MasonIntervalParameterInfo intervalInfo = (MasonIntervalParameterInfo) parameterInfo;

    			  field = new JPanel(new BorderLayout());

    			  String oldValueStr = String.valueOf(parameterInfo.getValue());
    			  if (oldField != null) {
    				  final JTextField oldTextField = (JTextField) oldField.getComponent(0);
    				  oldValueStr = oldTextField.getText();
    			  }

    			  final JTextField textField = new JTextField(oldValueStr);

    			  PercentJSlider tempSlider =  null;
    			  if (intervalInfo.isDoubleInterval())
    				  tempSlider = new PercentJSlider(intervalInfo.getIntervalMin().doubleValue(),intervalInfo.getIntervalMax().doubleValue(),
    						  Double.parseDouble(oldValueStr));
    			  else
    				  tempSlider = new PercentJSlider(intervalInfo.getIntervalMin().longValue(),intervalInfo.getIntervalMax().longValue(),
    						  Long.parseLong(oldValueStr));

    			  final PercentJSlider slider = tempSlider;
    			  slider.setMajorTickSpacing(100);
    			  slider.setMinorTickSpacing(10);
    			  slider.setPaintTicks(true);
    			  slider.setPaintLabels(true);
    			  slider.addChangeListener(new ChangeListener() {
    				  public void stateChanged(final ChangeEvent _) {
    					  if (slider.hasFocus()) {
    						  final String value = intervalInfo.isDoubleInterval() ? String.valueOf(slider.getDoubleValue()) :
    							  String.valueOf(slider.getLongValue());
    						  textField.setText(value);
    						  slider.setToolTipText(value);
    					  }
    				  }
    			  });

    			  textField.setInputVerifier(new InputVerifier() {
    				  public boolean verify(JComponent input) {
    					  final JTextField inputField = (JTextField) input;

    					  try {
    						  hideError();
    						  final String valueStr = inputField.getText().trim();
    						  if (intervalInfo.isDoubleInterval()) {
    							  final double value = Double.parseDouble(valueStr);
    							  if (intervalInfo.isValidValue(valueStr)) {
    								  slider.setValue(value);
    								  return true;
    							  } else 
    								  showError("Please specify a value between " + intervalInfo.getIntervalMin() + " and " + intervalInfo.getIntervalMax() + ".",
    										  inputField);
    							  return false;
    						  } else {
    							  final long value = Long.parseLong(valueStr);
    							  if (intervalInfo.isValidValue(valueStr)) {
    								  slider.setValue(value);
    								  return true;
    							  } else {
    								  showError("Please specify an integer value between " + intervalInfo.getIntervalMin() + " and " + intervalInfo.getIntervalMax() +
    										  ".",inputField);
    								  return false;
    							  }
    						  }
    					  } catch (final NumberFormatException _) {
    						  final String message = "The specified value is not a" + (intervalInfo.isDoubleInterval() ? "" : "n integer") + " number.";
    						  showError(message,inputField);
    						  return false;
    					  }

    				  }
    			  });

    			  textField.getDocument().addDocumentListener(new DocumentListener() {
    				  //					private Popup errorPopup;

    				  public void removeUpdate(final DocumentEvent _) {
    					  textFieldChanged();
    				  }

    				  public void insertUpdate(final DocumentEvent _) {
    					  textFieldChanged();
    				  }

    				  public void changedUpdate(final DocumentEvent _) {
    					  textFieldChanged();
    				  }

    				  private void textFieldChanged() {
    					  if (!textField.hasFocus()) {
    						  hideError();
    						  return;
    					  }

    					  try {
    						  hideError();
    						  final String valueStr = textField.getText().trim();
    						  if (intervalInfo.isDoubleInterval()) {
    							  final double value = Double.parseDouble(valueStr);
    							  if (intervalInfo.isValidValue(valueStr))
    								  slider.setValue(value);
    							  else 
    								  showError("Please specify a value between " + intervalInfo.getIntervalMin() + " and " + intervalInfo.getIntervalMax() + ".",
    										  textField);
    						  } else {
    							  final long value = Long.parseLong(valueStr);
    							  if (intervalInfo.isValidValue(valueStr))
    								  slider.setValue(value);
    							  else 
    								  showError("Please specify an integer value between " + intervalInfo.getIntervalMin() + " and " + intervalInfo.getIntervalMax() +
    										  ".",textField);
    						  }
    					  } catch (final NumberFormatException _) {
    						  final String message = "The specified value is not a" + (intervalInfo.isDoubleInterval() ? "" : "n integer") + " number.";
    						  showError(message,textField);
    					  }
    				  }
    			  });

    			  field.add(textField,BorderLayout.CENTER);
    			  field.add(slider,BorderLayout.SOUTH);
    		  } else {
    			  final Object value = oldField != null ? ((JTextField)oldField).getText()
    					  : parameterInfo.getValue();
    			  field = new JTextField(value.toString());
    			  ((JTextField)field).addActionListener(new ActionListener() {

    				  @Override
    				  public void actionPerformed(final ActionEvent e) {
    					  wizard.clickDefaultButton();
    				  }
    			  });
    		  }

    		  final JLabel parameterLabel = new JLabel(record.fieldName);

    		  final String description = parameterInfo.getDescription();
    		  if (description != null && !description.isEmpty()){
    			  parameterLabel.addMouseListener(new MouseAdapter() {

    				  @Override
    				  public void mouseEntered(final MouseEvent e) {
    					  final DescriptionPopupFactory popupFactory = DescriptionPopupFactory.getInstance();

    					  final Popup parameterDescriptionPopup = popupFactory.getPopup(parameterLabel, description, dashboard.getCssStyle());

    					  parameterDescriptionPopup.show();
    				  }

    			  });
    		  }

    		  if (oldNode != null) 
    			  userData.setSecond(field);
    		  else {
    			  final Pair<ParameterInfo,JComponent> pair = new Pair<ParameterInfo,JComponent>(parameterInfo,field);
    			  final DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(pair);
    			  parentNode.add(newNode);
    		  }

    		  if(field instanceof JCheckBox) {
    			  parameterLabel.setText("<html><div style=\"margin-bottom: 4pt; margin-top: 6pt; margin-left: 4pt\">" + parameterLabel.getText()
    					  + "</div></html>");
    			  formBuilder.append( parameterLabel, field );

    			  //            appendCheckBoxFieldToPresentation(
    			  //               formBuilder, parameterLabel.getText(), (JCheckBox) field);
    		  } else {
    			  formBuilder.append(parameterLabel, field);
    			  final CellConstraints constraints = formBuilder.getLayout().getConstraints(parameterLabel);
    			  constraints.vAlign = CellConstraints.TOP;
    			  constraints.insets = new Insets(5,0,0,0);
    			  formBuilder.getLayout().setConstraints(parameterLabel,constraints);
    		  }

    		  // prepare the parameterInfo for the param sweeps
    		  parameterInfo.setRuns(0);
    		  parameterInfo.setDefinitionType(ParameterInfo.CONST_DEF);
    		  parameterInfo.setValue(batchParameterInfo.getDefaultValue());
    		  info.add(parameterInfo);
    	  }
      }
      	appendVerticalSpaceToPresentation(formBuilder);
      
		final JPanel panel = formBuilder.getPanel();
		singleRunParametersPanel.add(panel);

		if (singleRunParametersPanel.getComponentCount() > 1) {
			panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(0,1,0,0,Color.GRAY),BorderFactory.createEmptyBorder(0,5,0,5)));
		} else {
			panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
		}
		
		Style.apply(panel, dashboard.getCssStyle());
		
		return info;
	}
	
	//----------------------------------------------------------------------------------------------------
	private DefaultMutableTreeNode findParameterInfoNode(final ParameterInfo info, final boolean checkParentValue) {
		if (info == null) return null;
		
		@SuppressWarnings("rawtypes")
		final Enumeration treeValues = parameterValueComponentTree.breadthFirstEnumeration();
		treeValues.nextElement(); // root node
		
		while (treeValues.hasMoreElements()) {
			final DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeValues.nextElement();
			@SuppressWarnings("unchecked")
			final Pair<ParameterInfo,JComponent> userData = (Pair<ParameterInfo,JComponent>) node.getUserObject();
			final ParameterInfo parameterInfo = userData.getFirst();
			
			if (checkParentValue && info instanceof ISubmodelGUIInfo && parameterInfo instanceof ISubmodelGUIInfo) {
				final ISubmodelGUIInfo sgi = (ISubmodelGUIInfo) info;
				final ISubmodelGUIInfo otherSgi = (ISubmodelGUIInfo) parameterInfo;
				if (info.equals(parameterInfo) && classEquals(sgi.getParentValue(),otherSgi.getParentValue()))
					return node;
			} else if (info.equals(parameterInfo)) 
				return node;
		}
		
		return null;
	}
	
	//----------------------------------------------------------------------------------------------------
	boolean classEquals(final Class<?> class1, final Class<?> class2) {
		if (class1 == class2) return true;
		
		if (class1 == null) return false;
		
		return class1.equals(class2);
	}

	//------------------------------------------------------------------------------
	/** Builds the parameter list on the gui from the <code>parameters</code> list. */
	private void createDefaultParameterList(final List<ParameterInfo> parameters) {
		final DefaultListModel model = new DefaultListModel();
		for (final ParameterInfo parameterInfo : parameters) 
			model.addElement(new AvailableParameter(parameterInfo, currentModelHandler.getModelClass()));
		parameterList.setModel(model); 
	}
	
	//------------------------------------------------------------------------------
	/** Edits the information object <code>info</code> so this method fills the appropriate
	 *  components with the informations of <code>info</code>.
	 */
	private void edit(final ParameterInfo info) { 
		changeText(info.getName(),info.getType());
		if (info instanceof SubmodelInfo) {
			final SubmodelInfo sInfo = (SubmodelInfo) info;
			editSubmodelInfo(sInfo);
		} else {
			String view = null;
			switch (info.getDefinitionType()) {
			case ParameterInfo.CONST_DEF : {
				if (info.isEnum() || info instanceof MasonChooserParameterInfo) {
					view = "ENUM";
					constDef.setSelected(true);
					incrDef.setEnabled(false);
					listDef.setEnabled(false);
					Object[] elements = null;
					if (info.isEnum()){
						@SuppressWarnings("unchecked")
						final
						Class<Enum<?>> type = (Class<Enum<?>>) info.getJavaType();
						elements = type.getEnumConstants();
					} else {
						final MasonChooserParameterInfo chooserInfo = (MasonChooserParameterInfo) info;
						elements = chooserInfo.getValidStrings();
					}
					final DefaultComboBoxModel model = (DefaultComboBoxModel)enumDefBox.getModel();
					model.removeAllElements();
					for (final Object object : elements) {
						model.addElement(object);
					}
					if (info.isEnum())
						enumDefBox.setSelectedItem(info.getValue());
					else 
						enumDefBox.setSelectedIndex((Integer)info.getValue());
				} else if (info.isFile()) {
					view = "FILE";
					constDef.setSelected(true);
					final File file = (File) info.getValue();
					if (file != null) {
						fileTextField.setText(file.getName());
						fileTextField.setToolTipText(file.getAbsolutePath());
					}
				} else {
					view = "CONST";
					constDef.setSelected(true);
					constDefField.setText(info.valuesToString());
				}
				break;
			}
			case ParameterInfo.LIST_DEF  : view = "LIST";
				listDef.setSelected(true);
				listDefArea.setText(info.valuesToString());
				break;
			case ParameterInfo.INCR_DEF  : view = "INCREMENT";
				incrDef.setSelected(true);
				incrStartValueField.setText(info.startToString());
				incrEndValueField.setText(info.endToString());
				incrStepField.setText(info.stepToString());
			}
			
			final CardLayout cl = (CardLayout) rightMiddle.getLayout();
			cl.show(rightMiddle,view);
			enableDisableSettings(true);
			if (!info.isNumeric()) 
				incrDef.setEnabled(false);
			if (info.isEnum() || info instanceof MasonChooserParameterInfo || info.isFile()) { 
				incrDef.setEnabled(false);
				listDef.setEnabled(false);
			}
			modifyButton.setEnabled(true);
		}
	}

	//----------------------------------------------------------------------------------------------------
	private void editSubmodelInfo(final SubmodelInfo sInfo) {
		constDef.setSelected(true);
		incrDef.setEnabled(false);
		listDef.setEnabled(false);
		cancelButton.setEnabled(true);
		final DefaultComboBoxModel model = (DefaultComboBoxModel) submodelTypeBox.getModel();
		model.removeAllElements();
		model.addElement("Loading class information...");
		final CardLayout cl = (CardLayout) rightMiddle.getLayout();
		cl.show(rightMiddle,"SUBMODEL");
		
		try {
			final ClassElement[] elements = fetchPossibleTypes(sInfo);
			model.removeAllElements();
			for (final ClassElement classElement : elements) 
				model.addElement(classElement);
			
			if (sInfo.getActualType() != null)
				submodelTypeBox.setSelectedItem(new ClassElement(sInfo.getActualType(), sInfo.getInstance()));
			submodelTypeBox.setEnabled(true);
			modifyButton.setEnabled(true);
		} catch (final ComboBoxIsTooFullException e) {
			String errorMsg = "Too much possibilities for " + sInfo.getName() + ". Please narrow down the domain by " + 
					  		  "defining the possible classes in the @Submodel annotation.";
			JOptionPane.showMessageDialog(wizard,new JLabel(errorMsg),"Error while analyizing model",JOptionPane.ERROR_MESSAGE);
			cancelButton.doClick();
		}
	}

	//------------------------------------------------------------------------------
	/** Changes the text on the right top corner of the page. The text can be the initial
	 *  commentary text ("Select a parameter to modify its settings") or
	 *  the name and type of the edited parameter.
	 * @param name name of the edited parameter (null if there is no editing parameter)
	 * @param type name of type of the edited parameter
	 */
	private void changeText(final String name, final String type) {
		if (name == null) {
			editedParameterText.setText(ORIGINAL_TEXT);
		} else {
			final String humanName = name.replaceAll("([A-Z])", " $1");
			editedParameterText.setText("<html><b>" + humanName + "</b>: " + type + "</html>");
		}
	}

	//----------------------------------------------------------------------------------------------------
	private boolean checkNumberOfTurnsField(final boolean singleRun) {
		try {
			final String value = singleRun ? numberOfTurnsField.getText() : numberOfTurnsFieldPSW.getText(); 
			Double.parseDouble(value);
			return true;
		} catch (final NumberFormatException _) {
			return false;
		}
	}

	//----------------------------------------------------------------------------------------------------
	private boolean checkNumberTimestepsIgnored(final boolean singleRun) {
		try {
			final String value = singleRun ? numberTimestepsIgnored.getText() : numberTimestepsIgnoredPSW.getText();
			Double.parseDouble(value);
			return true;
		} catch (final NumberFormatException _) {
			return false;
		}
	}

	//----------------------------------------------------------------------------------------------------
	private boolean modify() {
		final ParameterInATree userObj = (ParameterInATree) editedNode.getUserObject();
		
		final String[] errors = checkInput(userObj.info);
		if (errors != null && errors.length != 0) {
			Utilities.userAlert(sweepPanel,(Object)errors);
			return false;
		} else {
			modifyParameterInfo(userObj.info);
			resetSettings();
			modifyButton.setEnabled(false);
			
			if (!(userObj.info instanceof SubmodelInfo)) {
				final DefaultTreeModel model = (DefaultTreeModel) editedTree.getModel();
				model.nodeStructureChanged(editedNode);
			}
			
			editedNode = null;
			editedTree = null;
			
			updateNumberOfRuns();
			enableDisableSettings(false);
			return true;
		}
	}

	//------------------------------------------------------------------------------
	/** Checks the content of the editing components. 
	 * @param info the info object that belongs to the edited parameter
	 * @return the error messages in an array (or null if there is no error)
	 */
	private String[] checkInput(final ParameterInfo info) {
		final ArrayList<String> errors = new ArrayList<String>();
		if (constDef.isSelected()) {
			if (info.isEnum() || info instanceof MasonChooserParameterInfo) { 
				// well, the combo box must contain a valid value
			} else if (info instanceof SubmodelInfo) {
				final Object selectedObject = submodelTypeBox.getSelectedItem();
				if (!(selectedObject instanceof ClassElement))
					errors.add("Invalid type is selected for parameter " + info.getName());
				else {
					final ClassElement selectedElement = (ClassElement) selectedObject;
					if (selectedElement.clazz == null)
						errors.add("'Constant value' cannot be empty. Please select a type.");
				}
			} else if (info.isFile()) {
				if (fileTextField.getText().trim().isEmpty())
					log.warn("Empty string was specified as file parameter " + info.getName().replaceAll("([A-Z])"," $1"));

				final File file = new File(fileTextField.getToolTipText());
				if (!file.exists()) 
					errors.add("File " + fileTextField.getToolTipText() + " does not exist.");
			} else if (constDefField.getText().trim().equals(""))
				errors.add("'Constant value' cannot be empty.");
			else {
				final boolean valid = ParameterInfo.isValid(constDefField.getText().trim(),info.getType());
				if (!valid)
					errors.add("'Constant value' must be a valid " + getTypeText(info.getType()));
				errors.addAll(PlatformSettings.additionalParameterCheck(info,new String[] { constDefField.getText().trim() },ParameterInfo.CONST_DEF));
			}
		} else if (listDef.isSelected()) {
			String text = listDefArea.getText().trim();
			if (text.equals("")) 
				errors.add("'List of values' cannot be empty.");
			else {
				text = text.replaceAll("[\\s]+"," ");
				final String[] elements = text.split(" ");
				boolean goodList = true;
				for (final String element : elements)
					goodList = goodList && ParameterInfo.isValid(element.trim(),info.getType());
				if (!goodList)
					errors.add("All elements of the list must be a valid " + getTypeText(info.getType()));
//				else {
//					final Set<String> previous = new HashSet<String>(elements.length);
//					for (final String element : elements) {
//						if (previous.contains(element)) {
//							goodList = false;
//							break;
//						}
//						previous.add(element);
//					}
//					if (!goodList) {
//						final int result = Utilities.askUser(wizard,false,"Warning", "The list contains repetitive element(s).\nAre you sure?");
//						if (result == 0 && errors.size() == 0) // this doesn't work
//							return new String[0];
//					}
//				}
				errors.addAll(PlatformSettings.additionalParameterCheck(info,elements,ParameterInfo.LIST_DEF));
			}
		} else {
			boolean s = false, e = false, st = false; 
			if (incrStartValueField.getText().trim().equals("")) {
				errors.add("'Start value' cannot be empty.");
				s = true;
			} else {
				final boolean valid = ParameterInfo.isValid(incrStartValueField.getText().trim(),info.getType());
				if (!valid)
					errors.add("'Start value' must be a valid " + getTypeText(info.getType()));
			}
			if (incrEndValueField.getText().trim().equals("")) {
				errors.add("'End value' cannot be empty.");
				e = true;
			} else {
				final boolean valid = ParameterInfo.isValid(incrEndValueField.getText().trim(),info.getType());
				if (!valid)
					errors.add("'End value' must be a valid " + getTypeText(info.getType()));
			}
			if (incrStepField.getText().trim().equals("")) {
				errors.add("'Step' cannot be empty.");
				st = true;
			} else {
				final double d = Double.valueOf(incrStepField.getText().trim());
				if (d == 0)
					errors.add("'Step' cannot be zero.");
				else {
					final boolean valid = ParameterInfo.isValid(incrStepField.getText().trim(),info.getType());
					if (!valid)
						errors.add("'Step' must be a valid " + getTypeText(info.getType()));
				}
			}
			if (!(s || e || st))
				errors.addAll(PlatformSettings.additionalParameterCheck(info,new String[] { incrStartValueField.getText().trim(), 
																							incrEndValueField.getText().trim(), 
																							incrStepField.getText().trim() },ParameterInfo.INCR_DEF));
		}
		return errors.size()== 0 ? null : errors.toArray(new String[0]);
	}

	//------------------------------------------------------------------------------
	/** Returns the appropriate error message part according to the value of <code>type</code>. */
	String getTypeText(final String type) {
		if ("int".equals(type) || "Integer".equals(type))
			return "integer value.";
		if ("float".equals(type) || "Float".equals(type)
			|| "double".equals(type) || "Double".equals(type))
			return "real value.";
		if ("boolean".equals(type) || "Boolean".equals(type))
			return "boolean value (\"true\" or \"false\").";
		if ("String".equals(type))
			return "string that not contains any white space.";
		return type + ".";
	}

	//----------------------------------------------------------------------------------------------------
	private void updateNumberOfRuns() {
		final List<Integer> runNumbers = new ArrayList<Integer>(parameterTreeBranches.size());
		for (final ParameterCombinationGUI pGUI : parameterTreeBranches) {
			final int run = Page_Parameters.calculateNumberOfRuns(pGUI.combinationRoot);
			pGUI.updateRunDisplay(run);
			runNumbers.add(run);
		}
		
		int validMin = Integer.MAX_VALUE;
		for (final int runNumber : runNumbers) {
			if (runNumber > 1 && runNumber < validMin)
				validMin = runNumber;
		}
		
		for (int i = 0;i < parameterTreeBranches.size();++i) {
			final int runNumber = runNumbers.get(i);
			parameterTreeBranches.get(i).setWarning(runNumber > 1 && runNumber != validMin);
		}
	}


	//----------------------------------------------------------------------------------------------------
	public boolean needWarning() {
		if (parameterTreeBranches.isEmpty()) return false;
		
		for (final ParameterCombinationGUI pGUI : parameterTreeBranches) {
			if (pGUI.warningDisplay.getIcon() != null) return true;
		}
		
		return false;
	}
	
	//------------------------------------------------------------------------------
	/** Enables/disables the parameter editing components of the page according to
	 *  the value of <code>enabled</code>.
	 */
	private void enableDisableSettings(final boolean enabled) {
		constDef.setEnabled(enabled);
		listDef.setEnabled(enabled);
		incrDef.setEnabled(enabled);
		constDefField.setEnabled(enabled);
		listDefArea.setEnabled(enabled);
		incrStartValueField.setEnabled(enabled);
		incrEndValueField.setEnabled(enabled);
		incrStepField.setEnabled(enabled);
		enumDefBox.setEnabled(enabled);
		submodelTypeBox.setEnabled(enabled);
		fileTextField.setEnabled(enabled);
		fileBrowseButton.setEnabled(enabled);
		cancelButton.setEnabled(enabled);
	}

	//------------------------------------------------------------------------------
	/** Resets the parameter editing related components. */
	private void resetSettings() { 
		changeText(null,null);
		constDefField.setText("");
		listDefArea.setText("");
		incrStartValueField.setText("");
		incrEndValueField.setText("");
		incrStepField.setText("");
		fileTextField.setText("");
		fileTextField.setToolTipText("");
		
		constDef.setSelected(true);
		final CardLayout cl = (CardLayout) rightMiddle.getLayout();
		cl.show(rightMiddle,"CONST");
	}

	//------------------------------------------------------------------------------
	// Pre-condition : all input are valid
	/** Modifies the information object from the contents of the editing components of the page.<br>
	 *  Pre-condition: all input values are valid.
	 */
	private void modifyParameterInfo(final ParameterInfo info) { 
		info.clear();
		int defType = ParameterInfo.CONST_DEF;
		if (listDef.isSelected())
			defType = ParameterInfo.LIST_DEF;
		else if (incrDef.isSelected())
			defType = ParameterInfo.INCR_DEF;
		info.setDefinitionType(defType);
		switch (defType) {
		case ParameterInfo.CONST_DEF : {
			if (info.isEnum()) {
				info.setValue(enumDefBox.getSelectedItem());
			} else if (info instanceof MasonChooserParameterInfo) {
				info.setValue(enumDefBox.getSelectedIndex()); 
			} else if (info instanceof SubmodelInfo) {
				final SubmodelInfo sInfo = (SubmodelInfo) info;
				modifySubmodelParameterInfo(sInfo);
			} else if (info.isFile()) {
				info.setValue(ParameterInfo.getValue(fileTextField.getToolTipText(),info.getType()));
			} else {
				info.setValue(ParameterInfo.getValue(constDefField.getText().trim(),info.getType()));
			}
			
			break;
		}
		case ParameterInfo.LIST_DEF  : String text = listDefArea.getText().trim();
									   text = text.replaceAll("[\\s]+"," ");
									   final String[] elements = text.split(" ");
									   final List<Object> list = new ArrayList<Object>(elements.length);
									   for (final String element : elements) 
										  list.add(ParameterInfo.getValue(element,info.getType()));
									   info.setValues(list);
									   break;
		case ParameterInfo.INCR_DEF  : info.setStartValue((Number)ParameterInfo.getValue(incrStartValueField.getText().trim(),info.getType()));
									   info.setEndValue((Number)ParameterInfo.getValue(incrEndValueField.getText().trim(),info.getType()));
									   info.setStep((Number)ParameterInfo.getValue(incrStepField.getText().trim(),info.getType()));
									   break;
		}
	}

	//----------------------------------------------------------------------------------------------------
	private void modifySubmodelParameterInfo(final SubmodelInfo sInfo) {
		ClassElement aClassElement = (ClassElement) submodelTypeBox.getSelectedItem();
		final Class<?> newActualType = aClassElement.clazz;
		
		if (!newActualType.equals(sInfo.getActualType())) {
			sInfo.setActualType(newActualType, aClassElement.instance);
			addSubParametersToTree(sInfo,editedTree,editedNode);
			editedTree.expandPath(new TreePath(((DefaultTreeModel) editedTree.getModel()).getPathToRoot(editedNode)));
		} // else do nothing
		
	}
	
	//----------------------------------------------------------------------------------------------------
	private void addSubParametersToTree(final SubmodelInfo sInfo, final JTree tree, final DefaultMutableTreeNode node) {
		try {
			final List<ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>> subparameters = ParameterTreeUtils.fetchSubparameters(currentModelHandler,sInfo);
			
			final List<ParameterInfo> convertedSubparameters = new ArrayList<ParameterInfo>(subparameters.size());
			for (ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?> parameterInfo : subparameters) {
				final ParameterInfo converted = InfoConverter.parameterInfo2ParameterInfo(parameterInfo);
				converted.setRuns(0);
				convertedSubparameters.add(converted);
			}
			Collections.sort(convertedSubparameters);
			
			final DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();
			
			if (node.getChildCount() > 0) {
				node.removeAllChildren();
				treeModel.nodeStructureChanged(node);
			}
			
			for (final ParameterInfo pInfo : convertedSubparameters) {
				final DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(new ParameterInATree(pInfo, currentModelHandler.getModelClass()));
				treeModel.insertNodeInto(newNode,node,node.getChildCount());

				if (pInfo instanceof SubmodelInfo) {
					final SubmodelInfo ssInfo = (SubmodelInfo) pInfo;
					if (ssInfo.getActualType() != null)
						addSubParametersToTree(ssInfo, tree, newNode);
				}
			}

			//tree.expandPath(new TreePath(treeModel.getPathToRoot(node)));
		} catch (final ModelInformationException e) {
			sInfo.setActualType(null, null);
			JOptionPane.showMessageDialog(wizard, new JLabel(e.getMessage()), "Error while analyizing model", JOptionPane.ERROR_MESSAGE);
			e.printStackTrace();
			submodelTypeBox.setSelectedIndex(0);
		}
	}

	//----------------------------------------------------------------------------------------------------
	/**
	 * @return the numberOfTurnsField
	 */
	public double getNumberOfRequestedTurns() {
		if (tabbedPane.getSelectedIndex() == SINGLE_RUN_GUI_TABINDEX) 
			return Double.parseDouble(numberOfTurnsField.getText());
		else if (tabbedPane.getSelectedIndex() == PARAMSWEEP_GUI_TABINDEX) 
			return Double.parseDouble(numberOfTurnsFieldPSW.getText());
		else
			return gaSearchPanel.getNumberOfRequestedTurns();
	}

	//----------------------------------------------------------------------------------------------------
	public double getNumberTimestepsToIgnore() {
		if (tabbedPane.getSelectedIndex() == SINGLE_RUN_GUI_TABINDEX){
			return Double.parseDouble(numberTimestepsIgnored.getText());
		} else if (tabbedPane.getSelectedIndex() == PARAMSWEEP_GUI_TABINDEX) {
			return Double.parseDouble(numberTimestepsIgnoredPSW.getText());
		} else
			return 0.;
	}
	
	//----------------------------------------------------------------------------------------------------
	@Override
	public void actionPerformed(final ActionEvent e) {
		final String command = e.getActionCommand();

		if (ACTIONCOMMAND_EDIT.equals(command)){
			if (editedNode != null)
				cancelAllSelectionBut(null);
		} else if (command.equals("CONST") || command.equals("LIST") || command.equals("INCREMENT")) {
			final CardLayout cl = (CardLayout) rightMiddle.getLayout();
			cl.show(rightMiddle,command);
		} else if (command.equals("CANCEL")) {
			resetSettings();
			enableDisableSettings(false);
			modifyButton.setEnabled(false);
			editedNode = null;
			editedTree = null;
			cancelAllSelectionBut(null);
			enableDisableParameterCombinationButtons();
		} else if (command.equals("RUNS_FIELD") && PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.LOCAL)  
			constDef.grabFocus();
		else if (command.equals("CONST_FIELD") || command.equals("STEP_FIELD"))
			modifyButton.doClick();
		else if (command.equals("START_FIELD"))
			incrEndValueField.grabFocus();
		else if (command.equals("END_FIELD"))
			incrStepField.grabFocus();
		else if (ACTIONCOMMAND_ADD_BOX.equals(command)) 
			addBox();
		else if (ACTIONCOMMAND_BROWSE.equals(command))
			chooseFile();
	}

	//----------------------------------------------------------------------------------------------------
	private void addBox() {
		final JPanel panel = createAParameterBox(false);
		combinationsPanel.add(panel);
		combinationsPanel.revalidate();

		combinationsScrPane.invalidate();
		combinationsScrPane.validate();
		final JScrollBar verticalScrollBar = combinationsScrPane.getVerticalScrollBar();
		verticalScrollBar.setValue(verticalScrollBar.getMaximum());
	}
	
	//----------------------------------------------------------------------------------------------------
	private void chooseFile() {
		final JFileChooser fileDialog = new JFileChooser(!"".equals(fileTextField.getToolTipText()) ? fileTextField.getToolTipText() : currentDirectory);
		if (!"".equals(fileTextField.getToolTipText()))
			fileDialog.setSelectedFile(new File(fileTextField.getToolTipText()));
		int dialogResult = fileDialog.showOpenDialog(dashboard);
		if (dialogResult == JFileChooser.APPROVE_OPTION) {
			final File selectedFile = fileDialog.getSelectedFile();
			if (selectedFile != null) {
				currentDirectory = selectedFile.getAbsoluteFile().getParent();
				fileTextField.setText(selectedFile.getName());
				fileTextField.setToolTipText(selectedFile.getAbsolutePath());
			}
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	String getCurrentDirectory() { return currentDirectory; }
	void setCurrentDirectory(final String currentDirectory) { this.currentDirectory = currentDirectory; }
		
	//----------------------------------------------------------------------------------------------------
	private void cancelAllSelectionBut(JComponent exception) {
		if (exception != parameterList)
			parameterList.clearSelection();

		for (final ParameterCombinationGUI pGUI : parameterTreeBranches) {
			if (exception != pGUI.tree) 
				pGUI.tree.setSelectionPath(null);
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	private void updateDescriptionField(final Object... selectedValues) {
		if (selectedValues.length == 0) 
			parameterDescriptionLabel.setText("");
		else if (selectedValues.length == 1) {
			parameterDescriptionLabel.setText(selectedValues[0] != null ? ((AvailableParameter)selectedValues[0]).info.getDescription() : "");
		} else {
			String text = "";
			for (final Object selectedValue : selectedValues) {
				final AvailableParameter selectedParameter = (AvailableParameter) selectedValue;
				if (selectedParameter.info.getDescription() != null && !selectedParameter.info.getDescription().trim().isEmpty()) {
					final String humanName = selectedParameter.info.getName().replaceAll("([A-Z])", " $1");
					text += humanName + " -- " + selectedParameter.info.getDescription() + "\n\n";
				}
			}
			parameterDescriptionLabel.setText(text);
		}
		
		parameterDescriptionLabel.revalidate();
	}
	
	//----------------------------------------------------------------------------------------------------
	void showHideSubparameters(final JComboBox combobox, final SubmodelInfo info) {
		if ( !combobox.isDisplayable() ) {
			return;
		}
		final ClassElement classElement = (ClassElement) combobox.getSelectedItem();
		
		info.setActualType(classElement.clazz, classElement.instance);
		final int level = calculateParameterLevel(info);
		for (int i = singleRunParametersPanel.getComponentCount() - 1;i >= level + 1;--i) 
			singleRunParametersPanel.remove(i);
		
		if (classElement.clazz != null) {
			try {
				final List<ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>> subparameters = ParameterTreeUtils.fetchSubparameters(currentModelHandler,info);
				String title = "Configure " + info.getName().replaceAll("([A-Z])"," $1").trim();
				createAndDisplayAParameterPanel(subparameters,title,info, true, currentModelHandler);
			} catch (final ModelInformationException e) {
				info.setActualType(null, null);
				JOptionPane.showMessageDialog(wizard, new JLabel(e.getMessage()), "Error while analyizing model", JOptionPane.ERROR_MESSAGE);
				e.printStackTrace();
				combobox.setSelectedIndex(0);
			}
		}
		
		parametersScrollPane.invalidate();
		parametersScrollPane.validate();
		final JScrollBar horizontalScrollBar = parametersScrollPane.getHorizontalScrollBar();
		horizontalScrollBar.setValue(horizontalScrollBar.getMaximum());
	}

	//----------------------------------------------------------------------------------------------------
	private int calculateParameterLevel(final SubmodelInfo info) {
		SubmodelInfo _info = info;
		int level = 0;
		while (_info.getParent() != null) {
			level++;
			_info = _info.getParent();
		}
		
		return level;
	}
	
	//----------------------------------------------------------------------------------------------------
	private ParameterInfo findOriginalInfo(final ParameterInfo info) {
		for (final ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?> pInfo : batchParameters) {
			final ParameterInfo converted = InfoConverter.parameterInfo2ParameterInfo(pInfo);
			if (info.equals(converted)) {
				converted.setRuns(0);
				return converted;
			}
		}
		
		return null;
	}
	
	//----------------------------------------------------------------------------------------------------
	private void enableDisableParameterCombinationButtons() {
		final boolean selectionInTheList = parameterList.getSelectedIndex() >= 0; 
		
		for (ParameterCombinationGUI pGUI : parameterTreeBranches) {
			final boolean selectionInTheTree = pGUI.tree.getSelectionPath() != null;
			final boolean topLevelSelectionInTheTree = selectionInTheTree &&  
														pGUI.combinationRoot.isNodeChild((DefaultMutableTreeNode)pGUI.tree.getSelectionPath().getLastPathComponent()); 
					
			
			pGUI.addButton.setEnabled(selectionInTheList);
			pGUI.removeButton.setEnabled(topLevelSelectionInTheTree);
			pGUI.upButton.setEnabled(selectionInTheTree);
			pGUI.downButton.setEnabled(selectionInTheTree);
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	DWizard getWizard() { return wizard; }
	IModelHandler getCurrentModelHandler() { return currentModelHandler; }
	Dashboard getDashboard() { return dashboard; }
	
	//----------------------------------------------------------------------------------------------------
	ClassElement[] fetchPossibleTypes(final SubmodelInfo parameterInfo) throws ComboBoxIsTooFullException {
		List<Class<?>> possibleTypes = possibleTypesCache.get(parameterInfo.getName()); 
		
		if (possibleTypes == null)
			possibleTypes = parameterInfo.getPossibleTypes();
		if (possibleTypes == null || possibleTypes.isEmpty()) {
			possibleTypes = new ArrayList<Class<?>>();
			possibleTypes.add(parameterInfo.getJavaType());
			
			possibleTypes.addAll(getSubtypes(parameterInfo.getJavaType()));
			
			// delete all interfaces and abstract classes
			for (final Iterator<Class<?>> iter = possibleTypes.iterator();iter.hasNext();) {
				final Class<?> clazz = iter.next();
				if (Modifier.isAbstract(clazz.getModifiers()) || Modifier.isInterface(clazz.getModifiers()))
					iter.remove();
			}
		}
		
		possibleTypesCache.put(parameterInfo.getName(),possibleTypes);
		Collections.sort(possibleTypes,new Comparator<Class<?>>() {
			public int compare(final Class<?> class1, final Class<?> class2) {
				return class1.getName().compareTo(class2.getName());
			}
			
		});
		
		final ClassElement[] result = new ClassElement[possibleTypes.size() + 1];
		result[0] = new ClassElement(null, null);
		
		for (int i = 0;i < possibleTypes.size();++i) {
			if (possibleTypes.get(i).equals(parameterInfo.getActualType())) {
				result[i + 1] = new ClassElement(possibleTypes.get(i), parameterInfo.getInstance());
			} else {
				result[i + 1] = new ClassElement(possibleTypes.get(i), null);
			}
		}
		
		return result;
	}
	
	//----------------------------------------------------------------------------------------------------
	private Set<Class<?>> getSubtypes(final Class<?> type) throws ComboBoxIsTooFullException {
		final ClassLoader[] classloaders = new ClassLoader[] { currentModelHandler.getCustomClassLoader(),
															   currentModelHandler.getCustomClassLoader().getParent() };
		final ConfigurationBuilder builder = new ConfigurationBuilder().
				addUrls(ClasspathHelper.forClassLoader(currentModelHandler.getCustomClassLoader())). 
				addClassLoaders(classloaders).
				setScanners(new SubTypesScanner(false));
		final Reflections ref = new Reflections(builder);
		final Set<Class<?>> result = new HashSet<Class<?>>();
		final Set<String> subTypesStr = ref.getStore().getSubTypesOf(type.getName());
		if (subTypesStr.size() > MAX_SIZE_OF_SUBPARAMETER_COMBOBOX)
			throw new ComboBoxIsTooFullException();
		
		for (final String clsName : subTypesStr) {
			try {
				result.add(ReflectionUtils.forName(clsName,classloaders));
			} catch (final ReflectionsException e) {
				// intentionally blank
			}
		}

		return result;
	}
	
	//----------------------------------------------------------------------------------------------------
	private String checkInfos(final boolean submodel) {
		final DefaultListModel listModel = (DefaultListModel) parameterList.getModel();
		for (int i = 0;i < listModel.getSize();++i) {
			final AvailableParameter param = (AvailableParameter) listModel.get(i);
			final String invalid = submodel ? checkSubmodelInfo(param.info) : checkFileInfo(param);
			if (invalid != null)
				return invalid;
		}
		
		for (final ParameterCombinationGUI pGUI : parameterTreeBranches) {
			final DefaultMutableTreeNode root = pGUI.combinationRoot;
			@SuppressWarnings("rawtypes")
			final Enumeration nodes = root.breadthFirstEnumeration();
			nodes.nextElement(); // root
			while (nodes.hasMoreElements()) {
				final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement();
				final ParameterInATree userObj = (ParameterInATree) node.getUserObject();
				final String invalid = submodel ? checkSubmodelInfo(userObj.info) : checkFileInfo(userObj);
				if (invalid != null)
					return invalid;
			}
		}
		
		return null;
	}
	
	//----------------------------------------------------------------------------------------------------
	private String checkSubmodelInfo(final ParameterInfo info) {
		if (info instanceof SubmodelInfo) {
			final SubmodelInfo sInfo = (SubmodelInfo) info;
			if (sInfo.getActualType() == null)
				return sInfo.getName().replaceAll("([A-Z])"," $1");
		}
		
		return null;
	}
	
	//----------------------------------------------------------------------------------------------------
	private String checkFileInfo(final AvailableParameter parameter) {
		if (parameter.info.isFile()) {
			if (parameter.info.getValue() == null)
				return parameter.info.getName().replaceAll("([A-Z])"," $1");
		}
		
		return null;
	}
	
	//----------------------------------------------------------------------------------------------------
	private String checkInfosInGeneTree() {
		final DefaultTreeModel treeModel = gaSearchHandler.getChromosomeTree();
		final DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
		@SuppressWarnings("rawtypes")
		final Enumeration nodes = root.breadthFirstEnumeration();
		nodes.nextElement(); // root
		while (nodes.hasMoreElements()) {
			final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement();
			final ParameterOrGene userObj = (ParameterOrGene) node.getUserObject();
			final String invalid = checkSubmodelInfo(userObj.getInfo());
			if (invalid != null)
				return invalid;
		}
		
		return null;
	}
	
	//----------------------------------------------------------------------------------------------------
	private ParameterTree createParameterTreeFromParamSweepGUI() throws ModelInformationException {
		final ParameterTree result = new ParameterTree();
		
		final DefaultListModel listModel = (DefaultListModel) parameterList.getModel();
		for (int i = 0;i < listModel.getSize();++i) {
			final AvailableParameter param = (AvailableParameter) listModel.get(i);
			final AbstractParameterInfo<?> batchParameter = InfoConverter.parameterInfo2ParameterInfo(param.info);
			ParameterTreeUtils.addConstantParameterToParameterTree(batchParameter,result,currentModelHandler);
		}
		
		for (final ParameterCombinationGUI pGUI : parameterTreeBranches) {
			final DefaultMutableTreeNode root = pGUI.combinationRoot;
			@SuppressWarnings("rawtypes")
			final Enumeration nodes = root.breadthFirstEnumeration();
			nodes.nextElement(); // root;
			while (nodes.hasMoreElements()) {
				final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement();
				final ParameterInATree userObj = (ParameterInATree) node.getUserObject();
				ParameterTreeUtils.filterConstants(userObj,result,currentModelHandler);
			}
		}
		
		for (final ParameterCombinationGUI pGUI : parameterTreeBranches) {
			final DefaultMutableTreeNode root = pGUI.combinationRoot;
			@SuppressWarnings("rawtypes")
			final Enumeration nodes = root.preorderEnumeration();
			nodes.nextElement(); // root
			ParameterNode parent = result.getRoot();
			while (nodes.hasMoreElements()) {
				final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement();
				final ParameterInATree userObj = (ParameterInATree) node.getUserObject();
				if (ParameterTreeUtils.isMutableParameter(userObj)) {
					final AbstractParameterInfo<?> batchParameter = InfoConverter.parameterInfo2ParameterInfo(userObj.info);
					batchParameter.setRunNumber(1);
					final ParameterNode parameterNode = new ParameterNode(batchParameter);
					parent.add(parameterNode);
					parent = parameterNode;
				}
			}
		}
		
		return result;
	}
	
	//----------------------------------------------------------------------------------------------------
	private void hideError() {
		if (errorPopup != null) {
			errorPopup.hide();
			errorPopup = null;
		}
	}
	
	//----------------------------------------------------------------------------------------------------
	private void showError(final String message, final JTextField textField) {
		PopupFactory popupFactory = PopupFactory.getSharedInstance();
		Point locationOnScreen = textField.getLocationOnScreen();
		JLabel messageLabel = new JLabel(message);
		messageLabel.setBorder(new LineBorder(Color.RED, 2, true));
		errorPopup = popupFactory.getPopup(textField,messageLabel,locationOnScreen.x - 10,locationOnScreen.y - 30);
		errorPopup.show();
	}

	private static int calculateNumberOfRuns(DefaultMutableTreeNode combinationRoot) {
		int result = 1;
		@SuppressWarnings("rawtypes")
		final Enumeration combinationElements = combinationRoot.children();
		
		while (combinationElements.hasMoreElements()) {
			final DefaultMutableTreeNode node = (DefaultMutableTreeNode) combinationElements.nextElement();
			final ParameterInfo info = ((ParameterInATree)node.getUserObject()).info;
			
			if (info instanceof SubmodelInfo) 
				result *= calculateNumberOfRuns(node);
			else 
				result *= info.getMultiplicity();
		}
		
		return result;
	}
	
	
	//====================================================================================================
	// nested classes
	
	//----------------------------------------------------------------------------------------------------
	@SuppressWarnings("serial")
	static class ComboBoxIsTooFullException extends Exception {}
}
