eu.crisis_economics.abm.dashboard.GASearchPanel.java Source code

Java tutorial

Introduction

Here is the source code for eu.crisis_economics.abm.dashboard.GASearchPanel.java

Source

/*
 * This file is part of CRISIS, an economics simulator.
 * 
 * Copyright (C) 2015 AITIA International, Inc.
 * Copyright (C) 2015 John Kieran Phillips
 *
 * 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.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;

import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
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.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
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.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
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 org.jdesktop.swingx.JXLabel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ai.aitia.meme.paramsweep.batch.IModelInformation.ModelInformationException;
import ai.aitia.meme.paramsweep.batch.output.RecordableInfo;
import ai.aitia.meme.paramsweep.gui.info.MasonChooserParameterInfo;
import ai.aitia.meme.paramsweep.gui.info.ParameterInfo;
import ai.aitia.meme.paramsweep.gui.info.SubmodelInfo;
import ai.aitia.meme.paramsweep.intellisweepPlugin.utils.ga.GeneInfo;
import ai.aitia.meme.paramsweep.internal.platform.PlatformSettings;
import ai.aitia.meme.paramsweep.plugin.IStatisticsPlugin;
import ai.aitia.meme.paramsweep.utils.Utilities;
import ai.aitia.meme.utils.GUIUtils;
import ai.aitia.meme.utils.Utils;
import aurelienribon.ui.css.Style;

import com.jgoodies.forms.layout.CellConstraints;

import eu.crisis_economics.abm.dashboard.GASearchPanelModel.FitnessFunctionDirection;
import eu.crisis_economics.abm.dashboard.GASearchPanelModel.ModelListener;
import eu.crisis_economics.abm.dashboard.Page_Parameters.ComboBoxIsTooFullException;
import eu.crisis_economics.abm.dashboard.ga.IGAConfigurator;
import eu.crisis_economics.abm.dashboard.ga.IGAOperatorConfigurator;
import eu.crisis_economics.abm.dashboard.ga.IGASelectorConfigurator;

/**
 * @author Tams Mhr
 *
 */
public class GASearchPanel extends JPanel {

    //====================================================================================================
    // members

    private static final long serialVersionUID = 7957280032992002080L;

    private static final String NUMBER_OF_TURNS_IN_A_SIMULATION = "Number of turns in a simulation";

    private static final String GENE_SETTINGS_INT_RANGE_VALUE_PANEL = "int_range";
    private static final String GENE_SETTINGS_DOUBLE_RANGE_VALUE_PANEL = "double_range";
    private static final String GENE_SETTINGS_LIST_VALUE_PANEL = "list";
    private static final String PARAM_SETTINGS_CONSTANT_VALUE_PANEL = "constant";
    private static final String PARAM_SETTINGS_ENUM_VALUE_PANEL = "enum";
    private static final String PARAM_SETTINGS_FILE_VALUE_PANEL = "file";
    private static final String PARAM_SETTINGS_SUBMODEL_VALUE_PANEL = "submodel";

    private static final String DESCRIPTION_PANEL = "Description";
    private static final String OPERATOR_SETTINGS_PANEL_DEFAULT_PANEL = "DEFAULT";
    private static final String OPERATOR_SETTINGS_PANEL_TITLE_POSTFIX = "Operator settings";

    private static final Logger log = LoggerFactory.getLogger(GASearchPanel.class);
    private static final NumberFormat numberFormatter = NumberFormat.getInstance(Locale.US);

    static { // print double numbers rounded to 2 decimal digits using US format
        numberFormatter.setMaximumFractionDigits(2);
        numberFormatter.setMinimumFractionDigits(0);
        numberFormatter.setGroupingUsed(false);
    }

    private Page_Parameters parentPage;
    private JTextField numberOfTurnsField;
    private JSpinner populationSizeField;
    private JTextField populationRandomSeedField;
    private JRadioButton numberOfGenerationsRadioButton;
    private JSpinner numberOfGenerationsField;
    private JRadioButton fitnessLimitRadioButton;
    private JTextField fitnessLimitField;
    private JRadioButton fitnessMinimizeRadioButton;
    private JRadioButton fitnessMaximizeRadioButton;
    private JComboBox fitnessFunctionList;
    private JComboBox fitnessStatistics;
    private JSpinner fitnessTimeSeriesLength;
    private JTree geneTree;
    private JLabel numberLabel;
    protected Popup errorPopup;
    private JTextField constantField;
    private JTextField intMinField;
    private JTextField intMaxField;
    private JTextField doubleMinField;
    private JTextField doubleMaxField;
    private JTextArea valuesArea;
    private JComboBox enumDefBox;
    private JComboBox submodelTypeBox;
    private JTextField fileTextField;
    private JButton fileBrowseButton;

    private JRadioButton constantRButton;
    private JRadioButton doubleGeneValueRangeRButton;
    private JRadioButton intGeneValueRangeRButton;
    private JRadioButton listGeneValueRButton;

    private JPanel geneSettingsValuePanel;
    private JXLabel descriptionLabel;
    private JButton modifyButton;

    private DefaultMutableTreeNode editedNode;

    private JButton cancelButton;

    private JScrollPane mainScrPane;

    private JPanel operatorSettingsPanel;

    private CheckList selectorList;

    private CheckList operatorList;

    private GASearchPanelModel model;

    //====================================================================================================
    // methods

    //----------------------------------------------------------------------------------------------------
    public GASearchPanel(final GASearchPanelModel model, final Page_Parameters parentPage) {
        this.model = model;
        this.parentPage = parentPage;
        initSearchPanel(model);
    }

    //----------------------------------------------------------------------------------------------------
    public double getNumberOfRequestedTurns() {
        return Double.parseDouble(numberOfTurnsField.getText());
    }

    //----------------------------------------------------------------------------------------------------
    public void reset(final GASearchPanelModel model) {
        numberOfTurnsField.setText(double2String(model.getNumberOfTurns()));
        populationSizeField.setValue(model.getPopulationSize());
        populationRandomSeedField.setText(String.valueOf(model.getPopulationRandomSeed()));

        // create the stopping conditions panel
        numberOfGenerationsRadioButton.setSelected(true);
        numberOfGenerationsField.setValue(model.getNumberOfGenerations());
        fitnessLimitField.setText(String.valueOf(model.getFitnessLimitCriterion()));

        if (model.getNumberOfGenerations() < 0) {
            fitnessLimitRadioButton.setSelected(true);
            numberOfGenerationsField.setEnabled(false);
        } else {
            fitnessLimitField.setEnabled(false);
            numberOfGenerationsRadioButton.setSelected(true);
        }

        if (model.getFitnessFunctionDirection() == FitnessFunctionDirection.MINIMIZE)
            fitnessMinimizeRadioButton.setSelected(true);
        else
            fitnessMaximizeRadioButton.setSelected(true);

        fitnessFunctionList.setSelectedItem(model.getSelectedFitnessFunction());
        fitnessStatistics.setSelectedItem(model.getSelectedFitnessStatistics());
        fitnessTimeSeriesLength.setValue(model.getFitnessTimeSeriesLength());

        final CardLayout settingslayout = (CardLayout) operatorSettingsPanel.getLayout();
        settingslayout.show(operatorSettingsPanel, OPERATOR_SETTINGS_PANEL_DEFAULT_PANEL);
        ((TitledBorder) operatorSettingsPanel.getBorder()).setTitle(OPERATOR_SETTINGS_PANEL_TITLE_POSTFIX);
        descriptionLabel.setText("");

        final List<IGASelectorConfigurator> selectionOperators = model.getSelectionOperators();
        final List<IGASelectorConfigurator> selectedSelectionOperators = model.getSelectedSelectionOperators();

        int i = 0;
        for (final IGASelectorConfigurator selectionOperator : selectionOperators) {
            selectorList.setChecked(i, selectedSelectionOperators.contains(selectionOperator));
            ++i;
        }
        selectorList.clearSelection();

        final List<IGAOperatorConfigurator> geneticOperators = model.getGeneticOperators();
        final List<IGAOperatorConfigurator> selectedGeneticOperators = model.getSelectedGeneticOperators();

        i = 0;
        for (final IGAOperatorConfigurator operator : geneticOperators) {
            operatorList.setChecked(i, selectedGeneticOperators.contains(operator));
            ++i;
        }
        operatorList.clearSelection();

        numberLabel.setText("<html><b>Number of genes:</b> 0</html>");

        for (int j = 0; j < geneTree.getRowCount(); ++j)
            geneTree.expandRow(j);

        resetSettings();
        enableDisableSettings(false);
    }

    //----------------------------------------------------------------------------------------------------
    //   public void setSelectedFitnessFunction(final GASearchPanelModel gaSearchHandler) {
    //      fitnessFunctionList.setSelectedItem(gaSearchHandler.getSelectedFitnessFunction());
    //   }

    //====================================================================================================
    // assistant methods

    //----------------------------------------------------------------------------------------------------
    private void initSearchPanel(final GASearchPanelModel model) {
        model.addModelListener(new ModelListener() {
            public void fitnessFunctionAdded() {
                fitnessFunctionList.removeAllItems();
                final List<?> list = model.getFitnessFunctions();
                for (final Object fitnessFunction : list) {
                    fitnessFunctionList.addItem(fitnessFunction);
                }
            }

            public void fitnessFunctionsRemoved() {
                fitnessFunctionList.removeAllItems();
            }

            public void parameterAdded() {
                final DefaultTreeModel treeModel = model.getChromosomeTree();
                final DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
                geneTree.expandPath(new TreePath(treeModel.getPathToRoot(root)));
            }

            public void parametersRemoved() {
                parameterAdded(); // :)
            }
        });

        numberOfTurnsField = new JTextField(double2String(model.getNumberOfTurns()));
        numberOfTurnsField.setInputVerifier(new InputVerifier() {

            public boolean verify(final JComponent input) {
                if (errorPopup != null) {
                    errorPopup.hide();
                    errorPopup = null;
                }

                try {
                    final double value = Double.parseDouble(numberOfTurnsField.getText());
                    model.setNumberOfTurns(value);
                    return true;
                } catch (final NumberFormatException e) {
                    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));
                    errorPopup = popupFactory.getPopup(numberOfTurnsField, message, locationOnScreen.x - 10,
                            locationOnScreen.y - 30);
                    errorPopup.show();

                    return false;
                }
            }
        });

        final JPanel numberOfTurnsPanel = FormsUtils
                .build("p ' f:p:g", "01", NUMBER_OF_TURNS_IN_A_SIMULATION, numberOfTurnsField).getPanel();

        // create the population parameters panel
        populationSizeField = new JSpinner(
                new SpinnerNumberModel(model.getPopulationSize(), 2, Integer.MAX_VALUE, 1));
        populationSizeField.addChangeListener(new ChangeListener() {
            public void stateChanged(final ChangeEvent e) {
                model.setPopulationSize((Integer) ((JSpinner) e.getSource()).getValue());
            }
        });

        populationRandomSeedField = new JTextField(String.valueOf(model.getPopulationRandomSeed()));
        populationRandomSeedField.setInputVerifier(new InputVerifier() {

            public boolean verify(final JComponent input) {
                if (errorPopup != null) {
                    errorPopup.hide();
                    errorPopup = null;
                }

                try {
                    final int value = Integer.parseInt(populationRandomSeedField.getText());
                    model.setPopulationRandomSeed(value);
                    return true;
                } catch (final NumberFormatException e) {
                    final PopupFactory popupFactory = PopupFactory.getSharedInstance();
                    final Point locationOnScreen = populationRandomSeedField.getLocationOnScreen();
                    final JLabel message = new JLabel("Please specify an integer number!");
                    message.setBorder(new LineBorder(Color.RED, 2, true));
                    errorPopup = popupFactory.getPopup(populationRandomSeedField, message, locationOnScreen.x - 10,
                            locationOnScreen.y - 30);
                    errorPopup.show();

                    return false;
                }
            }
        });

        final JPanel populationPanel = FormsUtils.build("p ~ f:p:g", "01 ||" + "23", "Size", populationSizeField,
                "Random seed", populationRandomSeedField).getPanel();
        populationPanel.setBorder(
                BorderFactory.createTitledBorder(null, "Population", TitledBorder.LEADING, TitledBorder.BELOW_TOP));
        Style.registerCssClasses(populationPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        // create the stopping conditions panel
        numberOfGenerationsRadioButton = new JRadioButton("Number of generations");
        numberOfGenerationsField = new JSpinner(
                new SpinnerNumberModel(model.getNumberOfGenerations(), 1, Integer.MAX_VALUE, 1));
        numberOfGenerationsField.addChangeListener(new ChangeListener() {

            public void stateChanged(final ChangeEvent e) {
                model.setNumberOfGenerations((Integer) ((JSpinner) e.getSource()).getValue());
            }
        });
        numberOfGenerationsRadioButton.addChangeListener(new ChangeListener() {

            public void stateChanged(final ChangeEvent e) {
                if (numberOfGenerationsRadioButton.isSelected()) {
                    numberOfGenerationsField.setEnabled(true);
                    model.setFixNumberOfGenerations(true);
                } else
                    numberOfGenerationsField.setEnabled(false);
            }
        });

        fitnessLimitRadioButton = new JRadioButton("Fitness limit");
        fitnessLimitField = new JTextField(String.valueOf(model.getFitnessLimitCriterion()));
        fitnessLimitField.setInputVerifier(new InputVerifier() {

            public boolean verify(final JComponent input) {
                if (errorPopup != null) {
                    errorPopup.hide();
                    errorPopup = null;
                }

                try {
                    final double value = Double.parseDouble(fitnessLimitField.getText());
                    if (value < 0)
                        throw new NumberFormatException();
                    model.setFitnessLimitCriterion(value);
                    return true;
                } catch (final NumberFormatException e) {
                    final PopupFactory popupFactory = PopupFactory.getSharedInstance();
                    final Point locationOnScreen = fitnessLimitField.getLocationOnScreen();
                    final JLabel message = new JLabel(
                            "Please specify a non-negative (possibly floating point) number!");
                    message.setBorder(new LineBorder(Color.RED, 2, true));
                    errorPopup = popupFactory.getPopup(fitnessLimitField, message, locationOnScreen.x - 10,
                            locationOnScreen.y - 30);
                    errorPopup.show();

                    return false;
                }
            }
        });
        fitnessLimitRadioButton.addChangeListener(new ChangeListener() {

            public void stateChanged(final ChangeEvent e) {
                if (fitnessLimitRadioButton.isSelected()) {
                    fitnessLimitField.setEnabled(true);
                    model.setFixNumberOfGenerations(false);
                } else
                    fitnessLimitField.setEnabled(false);
            }
        });

        GUIUtils.createButtonGroup(numberOfGenerationsRadioButton, fitnessLimitRadioButton);

        if (model.getNumberOfGenerations() < 0) {
            fitnessLimitRadioButton.setSelected(true);
            numberOfGenerationsField.setEnabled(false);
            model.setFixNumberOfGenerations(false);
        } else {
            fitnessLimitField.setEnabled(false);
            numberOfGenerationsRadioButton.setSelected(true);
            model.setFixNumberOfGenerations(true);
        }

        final JPanel stoppingPanel = FormsUtils.build("p ~ f:p:g", "01 |" + "23", numberOfGenerationsRadioButton,
                numberOfGenerationsField, fitnessLimitRadioButton, fitnessLimitField).getPanel();
        stoppingPanel.setBorder(
                BorderFactory.createTitledBorder(null, "Stopping", TitledBorder.LEADING, TitledBorder.BELOW_TOP));
        Style.registerCssClasses(stoppingPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        // create the fitness function panel
        fitnessMinimizeRadioButton = new JRadioButton("Minimize");
        fitnessMaximizeRadioButton = new JRadioButton("Maximize");

        GUIUtils.createButtonGroup(fitnessMinimizeRadioButton, fitnessMaximizeRadioButton);
        GUIUtils.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (fitnessMinimizeRadioButton.isSelected())
                    model.setFitnessFunctionDirection(FitnessFunctionDirection.MINIMIZE);
                else if (fitnessMaximizeRadioButton.isSelected())
                    model.setFitnessFunctionDirection(FitnessFunctionDirection.MAXIMIZE);
            }
        }, fitnessMinimizeRadioButton, fitnessMaximizeRadioButton);

        if (model.getFitnessFunctionDirection() == FitnessFunctionDirection.MINIMIZE)
            fitnessMinimizeRadioButton.setSelected(true);
        else
            fitnessMaximizeRadioButton.setSelected(true);

        final JPanel fitnessButtonsPanel = new JPanel();
        Style.registerCssClasses(fitnessButtonsPanel, Dashboard.CSS_CLASS_COMMON_PANEL);
        fitnessButtonsPanel.add(fitnessMinimizeRadioButton);
        fitnessButtonsPanel.add(fitnessMaximizeRadioButton);

        fitnessFunctionList = new JComboBox(model.getFitnessFunctions().toArray(new Object[0]));
        fitnessFunctionList.setSelectedItem(model.getSelectedFitnessFunction());
        fitnessFunctionList.addItemListener(new ItemListener() {

            public void itemStateChanged(final ItemEvent e) {
                if (ItemEvent.SELECTED == e.getStateChange())
                    model.setSelectedFitnessFunction((RecordableInfo) e.getItem());
            }
        });

        initializeStatistics(model);
        final SpinnerNumberModel spinnerNumberModel = new SpinnerNumberModel();
        spinnerNumberModel.setStepSize(10);
        spinnerNumberModel.setValue(model.getFitnessTimeSeriesLength());
        fitnessTimeSeriesLength = new JSpinner(spinnerNumberModel);
        spinnerNumberModel.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                model.setFitnessTimeSeriesLength((Integer) spinnerNumberModel.getValue());
            }
        });

        JXLabel fitnessMessage = new JXLabel(
                "Please specify a function that always returns with non-negative value!");
        fitnessMessage.setLineWrap(true);
        final JPanel fitnessPanel = FormsUtils
                .build("p ~ f:p:g ~ p", "000 |" + "122 ||" + "345 ||" + "677 ||" + "888", fitnessButtonsPanel,
                        "Statistics", fitnessStatistics, "of the last", fitnessTimeSeriesLength, "values of",
                        "Fitness function", fitnessFunctionList, fitnessMessage)
                .getPanel();
        fitnessPanel.setBorder(
                BorderFactory.createTitledBorder(null, "Fitness", TitledBorder.LEADING, TitledBorder.BELOW_TOP));
        Style.registerCssClasses(fitnessPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        operatorSettingsPanel = new JPanel(new CardLayout());
        operatorSettingsPanel.setBorder(BorderFactory.createTitledBorder(null,
                OPERATOR_SETTINGS_PANEL_TITLE_POSTFIX, TitledBorder.LEADING, TitledBorder.BELOW_TOP));
        Style.registerCssClasses(operatorSettingsPanel, Dashboard.CSS_CLASS_COMMON_PANEL);
        operatorSettingsPanel.add(new JLabel("Here come the operator settings!"),
                OPERATOR_SETTINGS_PANEL_DEFAULT_PANEL);

        final JPanel operatorDescriptionPanel = new JPanel(new BorderLayout());
        operatorDescriptionPanel.setBorder(BorderFactory.createTitledBorder(null, DESCRIPTION_PANEL,
                TitledBorder.LEADING, TitledBorder.BELOW_TOP));
        Style.registerCssClasses(operatorDescriptionPanel, Dashboard.CSS_CLASS_COMMON_PANEL);
        operatorDescriptionPanel.add(initDescriptionPanel(), BorderLayout.CENTER);

        final List<IGASelectorConfigurator> selectionOperators = model.getSelectionOperators();
        final List<IGASelectorConfigurator> selectedSelectionOperators = model.getSelectedSelectionOperators();
        final CheckListModel selectorListModel = new CheckListModel(selectionOperators);
        selectorList = new CheckList(selectorListModel);
        Style.registerCssClasses(selectorList, Dashboard.CSS_CLASS_COMMON_PANEL);
        selectorList.setBorder(
                BorderFactory.createTitledBorder(null, "Selection", TitledBorder.LEADING, TitledBorder.BELOW_TOP));
        selectorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        int i = 0;
        for (final IGASelectorConfigurator selectionOperator : selectionOperators) {
            final JPanel settingspanel = selectionOperator.getSettingspanel();
            Style.registerCssClasses(settingspanel, Dashboard.CSS_CLASS_COMMON_PANEL);

            String description = selectionOperator.getDescription();
            Style.registerCssClasses(description, Dashboard.CSS_CLASS_COMMON_PANEL);
            operatorSettingsPanel.add(settingspanel, selectionOperator.getName());

            if (selectedSelectionOperators.contains(selectionOperator))
                selectorList.setChecked(i, true);

            ++i;
        }

        selectorList.addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(final ListSelectionEvent e) {
                final IGASelectorConfigurator operator = (IGASelectorConfigurator) selectorList.getSelectedValue();
                showOperatorDetails(operatorSettingsPanel, operatorDescriptionPanel, operator);
            }
        });

        selectorListModel.addListDataListener(new ListDataListener() {

            public void intervalRemoved(final ListDataEvent e) {
            }

            public void intervalAdded(final ListDataEvent e) {
            }

            public void contentsChanged(final ListDataEvent e) {
                final IGASelectorConfigurator operator = (IGASelectorConfigurator) selectorList.getSelectedValue();

                if (selectorList.getModel().getCheckedState(e.getIndex0()))
                    model.setSelectedSelectionOperator(operator);
                else
                    model.unsetSelectedSelectionOperator(operator);
            }
        });

        List<IGAOperatorConfigurator> geneticOperators = model.getGeneticOperators();
        List<IGAOperatorConfigurator> selectedGeneticOperators = model.getSelectedGeneticOperators();
        CheckListModel operatorListModel = new CheckListModel(geneticOperators);
        operatorList = new CheckList(operatorListModel);
        Style.registerCssClasses(operatorList, Dashboard.CSS_CLASS_COMMON_PANEL);
        operatorList.setBorder(BorderFactory.createTitledBorder(null, "Genetic operators", TitledBorder.LEADING,
                TitledBorder.BELOW_TOP));
        operatorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        i = 0;
        for (final IGAOperatorConfigurator operator : geneticOperators) {
            final JPanel settingsPanel = operator.getSettingspanel();
            Style.registerCssClasses(settingsPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

            String description = operator.getDescription();
            Style.registerCssClasses(description, Dashboard.CSS_CLASS_COMMON_PANEL);
            operatorSettingsPanel.add(settingsPanel, operator.getName());

            if (selectedGeneticOperators.contains(operator))
                operatorList.setChecked(i, true);

            ++i;
        }

        operatorList.addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(final ListSelectionEvent e) {
                final IGAOperatorConfigurator operator = (IGAOperatorConfigurator) operatorList.getSelectedValue();
                showOperatorDetails(operatorSettingsPanel, operatorDescriptionPanel, operator);
            }
        });

        operatorListModel.addListDataListener(new ListDataListener() {

            public void intervalRemoved(final ListDataEvent e) {
            }

            public void intervalAdded(final ListDataEvent e) {
            }

            public void contentsChanged(final ListDataEvent e) {
                final IGAOperatorConfigurator operator = (IGAOperatorConfigurator) operatorList.getSelectedValue();

                if (operatorList.getModel().getCheckedState(e.getIndex0()))
                    model.setSelectedGeneticOperator(operator);
                else
                    model.unsetSelectedGeneticOperator(operator);
            }
        });

        final JPanel operatorDetailsPanel = FormsUtils
                .build("f:p:g(0.5) f:p:g(0.5)", "01", operatorSettingsPanel, operatorDescriptionPanel).getPanel();
        Style.registerCssClasses(operatorDetailsPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        final JPanel gaSettingsPanel = FormsUtils
                .build("f:p:g", "0||" + "1||" + "2||" + "3||" + "4||" + "5||" + "6||" + "7",
                        new FormsUtils.Separator("General parameters"), numberOfTurnsPanel,
                        new FormsUtils.Separator("Genetic algorithm settings"), populationPanel, stoppingPanel,
                        fitnessPanel, selectorList, operatorList)
                .getPanel();
        Style.registerCssClasses(gaSettingsPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        // the chromosome panel
        final JScrollPane treeScrPane = new JScrollPane();
        geneTree = new JTree(model.getChromosomeTree());
        geneTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        geneTree.setCellRenderer(new ChromosomeTreeRenderer());

        geneTree.addTreeSelectionListener(new TreeSelectionListener() {
            public void valueChanged(final TreeSelectionEvent e) {
                final TreePath selectionPath = geneTree.getSelectionPath();

                boolean success = true;
                if (editedNode != null
                        && (selectionPath == null || !editedNode.equals(selectionPath.getLastPathComponent())))
                    success = modify();

                final DefaultTreeModel treeModel = model.getChromosomeTree();
                if (success) {
                    if (selectionPath != null) {
                        final DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectionPath
                                .getLastPathComponent();
                        final ParameterOrGene userObj = (ParameterOrGene) node.getUserObject();
                        if (userObj.getInfo().getDescription() != null
                                && !userObj.getInfo().getDescription().trim().isEmpty())
                            descriptionLabel.setText(userObj.getInfo().getDescription());
                        else
                            descriptionLabel.setText("");

                        if (!node.equals(editedNode)) {
                            if (!node.isRoot()
                                    && selectionPath.getPathCount() == treeModel.getPathToRoot(node).length) {
                                editedNode = node;
                                edit(userObj);
                            } else {
                                editedNode = null;
                                geneTree.setSelectionPath(null);
                                resetSettings();
                                enableDisableSettings(false);
                                descriptionLabel.setText("");
                            }
                        }
                    } else {
                        editedNode = null;
                        resetSettings();
                        enableDisableSettings(false);
                        descriptionLabel.setText("");
                    }
                } else
                    geneTree.setSelectionPath(new TreePath(treeModel.getPathToRoot(editedNode)));

            }
        });

        treeScrPane.setViewportView(geneTree);
        treeScrPane.setBorder(null);
        treeScrPane.setViewportBorder(null);

        numberLabel = new JLabel("<html><b>Number of genes:</b> 0</html>");
        final JPanel treePanel = FormsUtils
                .build("~ f:p:g", "0||" + "1||" + "2 f:p:g", numberLabel, new FormsUtils.Separator(""), treeScrPane)
                .getPanel();

        treePanel.setBorder(BorderFactory.createTitledBorder(""));
        Style.registerCssClasses(treePanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        constantRButton = new JRadioButton("Constant");
        doubleGeneValueRangeRButton = new JRadioButton("Double value range");
        intGeneValueRangeRButton = new JRadioButton("Integer value range");
        listGeneValueRButton = new JRadioButton("Value list");
        GUIUtils.createButtonGroup(constantRButton, doubleGeneValueRangeRButton, intGeneValueRangeRButton,
                listGeneValueRButton);

        geneSettingsValuePanel = new JPanel(new CardLayout());
        Style.registerCssClasses(geneSettingsValuePanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        constantField = new JTextField();
        constantField.setActionCommand("CONST_FIELD");

        final JPanel constantPanel = FormsUtils
                .build("p ~ p:g", "[DialogBorder]01 p", "Constant value", constantField).getPanel();
        Style.registerCssClasses(constantPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        enumDefBox = new JComboBox(new DefaultComboBoxModel());

        final JPanel enumDefPanel = FormsUtils.build("p ~ p:g", "[DialogBorder]01 p", "Constant value", enumDefBox)
                .getPanel();
        Style.registerCssClasses(enumDefPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        submodelTypeBox = new JComboBox();

        final JPanel submodelTypePanel = FormsUtils
                .build("p ~ p:g", "[DialogBorder]01", "Constant value", submodelTypeBox).getPanel();
        Style.registerCssClasses(submodelTypePanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        fileTextField = new JTextField();
        fileTextField.setActionCommand("FILE_FIELD");
        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(Page_Parameters.BROWSE_BUTTON_TEXT);
        fileBrowseButton.setActionCommand("FILE_BROWSE");

        final JPanel fileDefPanel = FormsUtils
                .build("p ~ p:g ~ p", "[DialogBorder]012", "File", fileTextField, fileBrowseButton).getPanel();
        Style.registerCssClasses(fileDefPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        intMinField = new JTextField();
        intMinField.setActionCommand("INT_MIN");
        intMaxField = new JTextField();
        intMaxField.setActionCommand("INT_MAX");
        doubleMinField = new JTextField();
        doubleMinField.setActionCommand("D_MIN");
        doubleMaxField = new JTextField();
        doubleMaxField.setActionCommand("D_MAX");
        valuesArea = new JTextArea();
        valuesArea.setToolTipText("Please specify ' ' (space) separated values!");
        valuesArea.setLineWrap(true);
        valuesArea.setWrapStyleWord(true);
        final JScrollPane valuesDefScr = new JScrollPane(valuesArea,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        final JPanel doublePanel = FormsUtils.build("p ' f:p:g", "[DialogBorder]01 p ||" + "23 p", "Minimum value",
                doubleMinField, "Maximum value", doubleMaxField).getPanel();
        Style.registerCssClasses(doublePanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        final JPanel intPanel = FormsUtils.build("p ' f:p:g", "[DialogBorder]01 p ||" + "23 p", "Minimum value",
                intMinField, "Maximum value", intMaxField).getPanel();
        Style.registerCssClasses(intPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        final JPanel valuesPanel = FormsUtils
                .build("p ' p:g", "[DialogBorder]01 f:p:g", "Value list", CellConstraints.TOP, valuesDefScr)
                .getPanel();
        Style.registerCssClasses(valuesPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        final JPanel emptyPanel = new JPanel();
        Style.registerCssClasses(emptyPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        geneSettingsValuePanel.add(emptyPanel, "NULL");
        geneSettingsValuePanel.add(constantPanel, PARAM_SETTINGS_CONSTANT_VALUE_PANEL);
        geneSettingsValuePanel.add(enumDefPanel, PARAM_SETTINGS_ENUM_VALUE_PANEL);
        geneSettingsValuePanel.add(fileDefPanel, PARAM_SETTINGS_FILE_VALUE_PANEL);
        geneSettingsValuePanel.add(submodelTypePanel, PARAM_SETTINGS_SUBMODEL_VALUE_PANEL);
        geneSettingsValuePanel.add(doublePanel, GENE_SETTINGS_DOUBLE_RANGE_VALUE_PANEL);
        geneSettingsValuePanel.add(intPanel, GENE_SETTINGS_INT_RANGE_VALUE_PANEL);
        geneSettingsValuePanel.add(valuesPanel, GENE_SETTINGS_LIST_VALUE_PANEL);

        final ItemListener itemListener = new ItemListener() {
            public void itemStateChanged(final ItemEvent _) {
                if (editedNode != null) {
                    final CardLayout layout = (CardLayout) geneSettingsValuePanel.getLayout();
                    if (doubleGeneValueRangeRButton.isSelected())
                        layout.show(geneSettingsValuePanel, GENE_SETTINGS_DOUBLE_RANGE_VALUE_PANEL);
                    else if (intGeneValueRangeRButton.isSelected())
                        layout.show(geneSettingsValuePanel, GENE_SETTINGS_INT_RANGE_VALUE_PANEL);
                    else if (listGeneValueRButton.isSelected())
                        layout.show(geneSettingsValuePanel, GENE_SETTINGS_LIST_VALUE_PANEL);
                    else if (constantRButton.isSelected()) {
                        final ParameterOrGene param = (ParameterOrGene) editedNode.getUserObject();
                        if (param.getInfo() instanceof SubmodelInfo)
                            layout.show(geneSettingsValuePanel, PARAM_SETTINGS_SUBMODEL_VALUE_PANEL);
                        else if (param.getInfo().isEnum() || param.getInfo() instanceof MasonChooserParameterInfo)
                            layout.show(geneSettingsValuePanel, PARAM_SETTINGS_ENUM_VALUE_PANEL);
                        else if (param.getInfo().isFile())
                            layout.show(geneSettingsValuePanel, PARAM_SETTINGS_FILE_VALUE_PANEL);
                        else
                            layout.show(geneSettingsValuePanel, PARAM_SETTINGS_CONSTANT_VALUE_PANEL);
                    }
                } else {
                    resetSettings();
                    enableDisableSettings(false);
                }
            }
        };
        constantRButton.addItemListener(itemListener);
        doubleGeneValueRangeRButton.addItemListener(itemListener);
        intGeneValueRangeRButton.addItemListener(itemListener);
        listGeneValueRButton.addItemListener(itemListener);

        final JPanel selectPanel = FormsUtils.build("f:p:g", "0||" + "1||" + "2||" + "3", constantRButton,
                doubleGeneValueRangeRButton, intGeneValueRangeRButton, listGeneValueRButton).getPanel();
        Style.registerCssClasses(selectPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        final JPanel buttonsPanel = new JPanel();
        modifyButton = new JButton("Modify");
        modifyButton.setActionCommand("EDIT");
        cancelButton = new JButton("Cancel");
        cancelButton.setActionCommand("CANCEL");
        GUIUtils.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                final String cmd = e.getActionCommand();
                if ("EDIT".equals(cmd))
                    edit();
                else if ("CANCEL".equals(cmd))
                    cancel();
                else if ("CONST_FIELD".equals(cmd) || "INT_MAX".equals(cmd) || "D_MAX".equals(cmd))
                    modifyButton.doClick();
                else if ("INT_MIN".equals(cmd))
                    intMaxField.grabFocus();
                else if ("D_MIN".equals(cmd))
                    doubleMaxField.grabFocus();
                else if ("FILE_BROWSE".equals(cmd))
                    chooseFile();
            }

            private void edit() {
                if (editedNode != null)
                    geneTree.setSelectionPath(null);
            }

            private void cancel() {
                resetSettings();
                enableDisableSettings(false);
                editedNode = null;
                geneTree.setSelectionPath(null);
            }

            private void chooseFile() {
                final JFileChooser fileDialog = new JFileChooser(
                        !"".equals(fileTextField.getToolTipText()) ? fileTextField.getToolTipText()
                                : parentPage.getCurrentDirectory());
                if (!"".equals(fileTextField.getToolTipText()))
                    fileDialog.setSelectedFile(new File(fileTextField.getToolTipText()));
                int dialogResult = fileDialog.showOpenDialog(parentPage.getWizard());
                if (dialogResult == JFileChooser.APPROVE_OPTION) {
                    final File selectedFile = fileDialog.getSelectedFile();
                    if (selectedFile != null) {
                        parentPage.setCurrentDirectory(selectedFile.getAbsoluteFile().getParent());
                        fileTextField.setText(selectedFile.getName());
                        fileTextField.setToolTipText(selectedFile.getAbsolutePath());
                    }
                }
            }
        }, modifyButton, cancelButton, constantField, fileTextField, intMinField, intMaxField, doubleMinField,
                doubleMaxField, fileBrowseButton);
        buttonsPanel.add(modifyButton);
        buttonsPanel.add(cancelButton);

        final JPanel geneSetterPanel = FormsUtils
                .build("f:p:g", "0||" + "1 f:p:g||" + "2 p", selectPanel, geneSettingsValuePanel, buttonsPanel)
                .getPanel();

        geneSetterPanel.setBorder(BorderFactory.createTitledBorder(null, "Gene/parameter settings",
                TitledBorder.LEADING, TitledBorder.BELOW_TOP));
        Style.registerCssClasses(geneSetterPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        final JPanel rightTop = FormsUtils.build("f:p:g p", "01 f:p:g", treePanel, geneSetterPanel).getPanel();
        rightTop.setBorder(
                BorderFactory.createTitledBorder(null, "Chromosome", TitledBorder.LEADING, TitledBorder.BELOW_TOP));
        Style.registerCssClasses(rightTop, Dashboard.CSS_CLASS_COMMON_PANEL);

        final JPanel mainPanel = FormsUtils
                .build("p f:p:g", "01 f:p:g||" + "02 p", gaSettingsPanel, rightTop, operatorDetailsPanel)
                .getPanel();
        mainPanel.setBorder(BorderFactory.createTitledBorder(""));
        Style.registerCssClasses(mainPanel, Dashboard.CSS_CLASS_COMMON_PANEL);

        setLayout(new BorderLayout());
        mainScrPane = new JScrollPane(mainPanel);
        mainScrPane.setBorder(null);
        mainScrPane.setViewportBorder(null);
        add(mainScrPane, BorderLayout.CENTER);

        resetSettings();
        enableDisableSettings(false);
    }

    private void initializeStatistics(final GASearchPanelModel model) {
        fitnessStatistics = new JComboBox(model.getFitnessStatistics().toArray(new Object[0]));
        fitnessStatistics.setRenderer(new DefaultListCellRenderer() {

            private static final long serialVersionUID = 1L;

            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
                    boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                IStatisticsPlugin plugin = (IStatisticsPlugin) value;

                this.setText(plugin.getName());
                this.setToolTipText(plugin.getDescription());

                return this;
            }
        });
        fitnessStatistics.setSelectedItem(model.getSelectedFitnessStatistics());
        fitnessStatistics.addItemListener(new ItemListener() {

            public void itemStateChanged(final ItemEvent e) {
                if (ItemEvent.SELECTED == e.getStateChange())
                    model.setSelectedFitnessStatistics((IStatisticsPlugin) e.getItem());
            }
        });

    }

    //----------------------------------------------------------------------------------------------------
    @SuppressWarnings("unused")
    private JCheckBox createOperatorCheckBox(final JPanel operatorSettingsPanel,
            final JPanel operatorDescriptionPanel, final IGASelectorConfigurator operator,
            final GASearchPanelModel model) {
        JCheckBox checkBox = new JCheckBox(operator.getName());
        operatorSettingsPanel.add(operator.getSettingspanel(), operator.getName());
        JXLabel descriptionLabel = new JXLabel(operator.getDescription());
        descriptionLabel.setLineWrap(true);
        descriptionLabel.setVerticalAlignment(SwingConstants.TOP);
        descriptionLabel.setPreferredSize(new Dimension(200, 200));
        operatorDescriptionPanel.add(descriptionLabel, operator.getName());

        checkBox.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    CardLayout settingslayout = (CardLayout) operatorSettingsPanel.getLayout();
                    settingslayout.show(operatorSettingsPanel, operator.getName());
                    ((TitledBorder) operatorSettingsPanel.getBorder()).setTitle(operator.getName());
                    operatorSettingsPanel.repaint();

                    CardLayout descriptionLayout = (CardLayout) operatorDescriptionPanel.getLayout();
                    descriptionLayout.show(operatorDescriptionPanel, operator.getName());

                    //               model.setSelectedOperator(operator);
                } else {
                    CardLayout settingslayout = (CardLayout) operatorSettingsPanel.getLayout();
                    settingslayout.show(operatorSettingsPanel, OPERATOR_SETTINGS_PANEL_DEFAULT_PANEL);
                    ((TitledBorder) operatorSettingsPanel.getBorder())
                            .setTitle(OPERATOR_SETTINGS_PANEL_TITLE_POSTFIX);
                    operatorSettingsPanel.repaint();

                    CardLayout descriptionLayout = (CardLayout) operatorDescriptionPanel.getLayout();
                    descriptionLayout.show(operatorDescriptionPanel, OPERATOR_SETTINGS_PANEL_DEFAULT_PANEL);

                    //               model.removeSelectedOperator(operator);
                }
            }
        });

        checkBox.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                CardLayout settingslayout = (CardLayout) operatorSettingsPanel.getLayout();
                settingslayout.show(operatorSettingsPanel, operator.getName());
                ((TitledBorder) operatorSettingsPanel.getBorder()).setTitle(operator.getName());
                operatorSettingsPanel.repaint();

                CardLayout descriptionLayout = (CardLayout) operatorDescriptionPanel.getLayout();
                descriptionLayout.show(operatorDescriptionPanel, operator.getName());
            }
        });

        return checkBox;
    }

    //----------------------------------------------------------------------------------------------------
    private JScrollPane initDescriptionPanel() {
        descriptionLabel = new JXLabel("");
        descriptionLabel.setLineWrap(true);
        descriptionLabel.setVerticalAlignment(SwingConstants.TOP);

        JScrollPane scrollPane = new JScrollPane(descriptionLabel);
        Style.registerCssClasses(scrollPane, ".borderless");
        scrollPane.getViewportBorder();
        scrollPane.setViewportBorder(null);
        scrollPane.setPreferredSize(new Dimension(200, 100));

        return scrollPane;
    }

    //----------------------------------------------------------------------------------------------------
    protected void showOperatorDetails(final JPanel operatorSettingsPanel, final JPanel operatorDescriptionPanel,
            final IGAConfigurator operator) {
        if (operator != null) {
            CardLayout settingslayout = (CardLayout) operatorSettingsPanel.getLayout();
            settingslayout.show(operatorSettingsPanel, operator.getName());
            ((TitledBorder) operatorSettingsPanel.getBorder()).setTitle(operator.getName());
            operatorSettingsPanel.repaint();
            descriptionLabel.setText(operator.getDescription());
        } else
            descriptionLabel.setText("");

    }

    //-------------------------------------------------------------------------------------------------
    /**
     * Utility method that returns the string representation of a double value (rounded to 2 decimal
     * digits using US format) 
     */
    private static String double2String(final double d) {
        BigDecimal bd = new BigDecimal(d);
        bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
        return numberFormatter.format(bd);
    }

    //------------------------------------------------------------------------------
    /** Enables/disables the parameter editing components of the page according to
     *  the value of <code>enabled</code>.
     */
    private void enableDisableSettings(final boolean enabled) {
        constantRButton.setEnabled(enabled);
        intGeneValueRangeRButton.setEnabled(enabled);
        doubleGeneValueRangeRButton.setEnabled(enabled);
        listGeneValueRButton.setEnabled(enabled);
        constantField.setEnabled(enabled);
        enumDefBox.setEnabled(enabled);
        submodelTypeBox.setEnabled(enabled);
        fileTextField.setEnabled(enabled);
        fileBrowseButton.setEnabled(enabled);
        intMinField.setEnabled(enabled);
        intMaxField.setEnabled(enabled);
        doubleMinField.setEnabled(enabled);
        doubleMaxField.setEnabled(enabled);
        valuesArea.setEnabled(enabled);
        modifyButton.setEnabled(enabled);
        cancelButton.setEnabled(enabled);
    }

    //------------------------------------------------------------------------------
    /** Resets the parameter editing related components. */
    private void resetSettings() {
        constantRButton.setSelected(false);
        intGeneValueRangeRButton.setSelected(false);
        doubleGeneValueRangeRButton.setSelected(false);
        ;
        listGeneValueRButton.setSelected(false);
        ;
        constantField.setText("");
        fileTextField.setText("");
        intMinField.setText("");
        intMaxField.setText("");
        doubleMinField.setText("");
        doubleMaxField.setText("");
        valuesArea.setText("");
        modifyButton.setEnabled(false);
        cancelButton.setEnabled(false);

        final CardLayout cl = (CardLayout) geneSettingsValuePanel.getLayout();
        cl.show(geneSettingsValuePanel, "NULL");
    }

    //----------------------------------------------------------------------------------------------------
    private void edit(final ParameterOrGene param) {
        enableDisableSettings(true);
        String view = PARAM_SETTINGS_CONSTANT_VALUE_PANEL;
        if (param.isGene()) {
            editGene(param.getGeneInfo());
            return;
        } else if (param.getInfo() instanceof SubmodelInfo) {
            final SubmodelInfo sInfo = (SubmodelInfo) param.getInfo();
            editSubmodelInfo(sInfo);
            return;
        } else if (param.getInfo().isEnum() || param.getInfo() instanceof MasonChooserParameterInfo) {
            view = PARAM_SETTINGS_ENUM_VALUE_PANEL;
            intGeneValueRangeRButton.setEnabled(false);
            doubleGeneValueRangeRButton.setEnabled(false);
            listGeneValueRButton.setEnabled(false);
            constantRButton.setSelected(true);

            final ParameterInfo info = param.getInfo();
            final Object selected = info.getValue();
            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(selected);
            else
                enumDefBox.setSelectedIndex((Integer) selected);
        } else if (param.getInfo().isFile()) {
            view = PARAM_SETTINGS_FILE_VALUE_PANEL;
            constantRButton.setSelected(true);
            final File file = (File) param.getInfo().getValue();
            if (file != null) {
                fileTextField.setText(file.getName());
                fileTextField.setToolTipText(file.getAbsolutePath());
            }
        } else {
            constantRButton.setSelected(true);
            constantField.setText(param.getInfo().valuesToString());
        }

        final CardLayout cl = (CardLayout) geneSettingsValuePanel.getLayout();
        cl.show(geneSettingsValuePanel, view);
        if (!param.getInfo().isNumeric()) {
            intGeneValueRangeRButton.setEnabled(false);
            doubleGeneValueRangeRButton.setEnabled(false);
            listGeneValueRButton.setEnabled(false);
        }
    }

    //----------------------------------------------------------------------------------------------------
    private void editSubmodelInfo(final SubmodelInfo sInfo) {
        constantRButton.setSelected(true);
        intGeneValueRangeRButton.setEnabled(false);
        doubleGeneValueRangeRButton.setEnabled(false);
        listGeneValueRButton.setEnabled(false);
        final Class<?> actualType = sInfo.getActualType();
        final DefaultComboBoxModel model = (DefaultComboBoxModel) submodelTypeBox.getModel();
        model.removeAllElements();
        model.addElement("Loading class information...");
        final CardLayout cl = (CardLayout) geneSettingsValuePanel.getLayout();
        cl.show(geneSettingsValuePanel, PARAM_SETTINGS_SUBMODEL_VALUE_PANEL);

        try {
            final ClassElement[] elements = parentPage.fetchPossibleTypes(sInfo);
            model.removeAllElements();
            for (final ClassElement classElement : elements)
                model.addElement(classElement);

            if (actualType != null)
                submodelTypeBox.setSelectedItem(new ClassElement(actualType, sInfo.getInstance()));
            submodelTypeBox.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(parentPage.getWizard(), new JLabel(errorMsg),
                    "Error while analyizing model", JOptionPane.ERROR_MESSAGE);

            resetSettings();
            enableDisableSettings(false);
            editedNode = null;
        }
    }

    //----------------------------------------------------------------------------------------------------
    private void editGene(final GeneInfo geneInfo) {
        String view = null;
        if (GeneInfo.LIST.equals(geneInfo.getValueType())) {
            view = GENE_SETTINGS_LIST_VALUE_PANEL;
            listGeneValueRButton.setSelected(true);
            valuesArea.setText(Utils.join(geneInfo.getValueRange(), " "));
        } else {
            if (geneInfo.isIntegerVals()) {
                view = GENE_SETTINGS_INT_RANGE_VALUE_PANEL;
                intGeneValueRangeRButton.setSelected(true);
                intMinField.setText(String.valueOf(geneInfo.getMinValue()));
                intMaxField.setText(String.valueOf(geneInfo.getMaxValue()));
            } else {
                view = GENE_SETTINGS_DOUBLE_RANGE_VALUE_PANEL;
                doubleGeneValueRangeRButton.setSelected(true);
                doubleMinField.setText(String.valueOf(geneInfo.getMinValue()));
                doubleMaxField.setText(String.valueOf(geneInfo.getMaxValue()));
            }
        }

        final CardLayout cl = (CardLayout) geneSettingsValuePanel.getLayout();
        cl.show(geneSettingsValuePanel, view);
    }

    //----------------------------------------------------------------------------------------------------
    private String[] checkInput(final ParameterOrGene param) {
        final List<String> errors = new ArrayList<String>();

        if (constantRButton.isSelected()) {
            final ParameterInfo info = param.getInfo();

            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 (constantField.getText().trim().equals(""))
                errors.add("'Constant value' cannot be empty.");
            else {
                final boolean valid = ParameterInfo.isValid(constantField.getText().trim(), info.getType());
                if (!valid)
                    errors.add("'Constant value' must be a valid " + parentPage.getTypeText(info.getType()) + ".");

                errors.addAll(PlatformSettings.additionalParameterCheck(info,
                        new String[] { constantField.getText().trim() }, ParameterInfo.CONST_DEF));
            }
        } else if (intGeneValueRangeRButton.isSelected()) {
            final String minFieldText = intMinField.getText();
            final String maxFieldText = intMaxField.getText();
            Long minValue = null;
            Long maxValue = null;

            if (minFieldText == null || minFieldText.trim().isEmpty())
                errors.add("'Minimum value' cannot be empty.");
            else {
                try {
                    minValue = new Long(minFieldText.trim());

                    final boolean valid = ParameterInfo.isValid(minFieldText, param.getInfo().getType());
                    if (!valid)
                        errors.add("'Minimum value' must be a valid "
                                + parentPage.getTypeText(param.getInfo().getType()) + ".");

                    errors.addAll(PlatformSettings.additionalParameterCheck(param.getInfo(),
                            new String[] { minFieldText.trim() }, ParameterInfo.CONST_DEF));
                } catch (final NumberFormatException _) {
                    errors.add("'Minimum value' must be a valid integer number.");
                }
            }

            if (maxFieldText == null || maxFieldText.trim().isEmpty())
                errors.add("'Maximum value' cannot be empty.");
            else {
                try {
                    maxValue = new Long(maxFieldText.trim());

                    final boolean valid = ParameterInfo.isValid(maxFieldText, param.getInfo().getType());
                    if (!valid)
                        errors.add("'Maximum value' must be a valid "
                                + parentPage.getTypeText(param.getInfo().getType()) + ".");

                    errors.addAll(PlatformSettings.additionalParameterCheck(param.getInfo(),
                            new String[] { maxFieldText.trim() }, ParameterInfo.CONST_DEF));
                } catch (final NumberFormatException _) {
                    errors.add("'Maximum value' must be a valid integer number.");
                }
            }

            if (minValue != null && maxValue != null) {
                if (minValue.longValue() > maxValue.longValue())
                    errors.add("Please specify a non-empty interval!");
            }
        } else if (doubleGeneValueRangeRButton.isSelected()) {
            final String minFieldText = doubleMinField.getText();
            final String maxFieldText = doubleMaxField.getText();
            Double minValue = null;
            Double maxValue = null;

            if (minFieldText == null || minFieldText.trim().isEmpty())
                errors.add("'Minimum value' cannot be empty.");
            else {
                try {
                    minValue = new Double(minFieldText.trim());

                    final boolean valid = ParameterInfo.isValid(minFieldText, param.getInfo().getType());
                    if (!valid)
                        errors.add("'Minimum value' must be a valid "
                                + parentPage.getTypeText(param.getInfo().getType()) + ".");

                    errors.addAll(PlatformSettings.additionalParameterCheck(param.getInfo(),
                            new String[] { minFieldText.trim() }, ParameterInfo.CONST_DEF));
                } catch (final NumberFormatException _) {
                    errors.add("'Minimum value' must be a valid number.");
                }
            }

            if (maxFieldText == null || maxFieldText.trim().isEmpty())
                errors.add("'Maximum value' cannot be empty.");
            else {
                try {
                    maxValue = new Double(maxFieldText.trim());

                    final boolean valid = ParameterInfo.isValid(maxFieldText, param.getInfo().getType());
                    if (!valid)
                        errors.add("'Maximum value' must be a valid "
                                + parentPage.getTypeText(param.getInfo().getType()) + ".");

                    errors.addAll(PlatformSettings.additionalParameterCheck(param.getInfo(),
                            new String[] { maxFieldText.trim() }, ParameterInfo.CONST_DEF));
                } catch (final NumberFormatException _) {
                    errors.add("'Maximum value' must be a valid number.");
                }
            }

            if (minValue != null && maxValue != null) {
                if (minValue.doubleValue() > maxValue.doubleValue())
                    errors.add("Please specify a non-empty interval!");
            }

        } else if (listGeneValueRButton.isSelected()) {
            if (valuesArea.getText() == null || valuesArea.getText().trim().isEmpty())
                errors.add("'Value list' cannot be empty.");
            else {
                try {
                    final List<Object> valueList = new ArrayList<Object>();
                    String values = valuesArea.getText().trim();
                    values = values.replaceAll("\\s+", " ");
                    final StringTokenizer tokenizer = new StringTokenizer(values, " ");
                    while (tokenizer.hasMoreTokens()) {
                        final String strValue = tokenizer.nextToken();

                        final boolean valid = ParameterInfo.isValid(strValue, param.getInfo().getType());
                        if (!valid)
                            errors.add("'" + strValue + "' is not a valid "
                                    + parentPage.getTypeText(param.getInfo().getType()) + ".");

                        valueList.add(parseListElement(param.getInfo().getJavaType(), strValue));
                    }

                    errors.addAll(PlatformSettings.additionalParameterCheck(param.getInfo(), values.split(" "),
                            ParameterInfo.LIST_DEF));
                } catch (final NumberFormatException _) {
                    errors.add("All element of the value list must be a valid number.");
                }
            }
        }

        return errors.isEmpty() ? null : errors.toArray(new String[0]);
    }

    //----------------------------------------------------------------------------------------------------
    private Object parseListElement(final Class<?> type, final String strValue) {
        if (type.equals(Double.class) || type.equals(Float.class) || type.equals(Double.TYPE)
                || type.equals(Float.TYPE))
            return Double.parseDouble(strValue);

        return Long.parseLong(strValue);
    }

    //----------------------------------------------------------------------------------------------------
    private boolean modify() {
        final ParameterOrGene userObj = (ParameterOrGene) editedNode.getUserObject();

        final String[] errors = checkInput(userObj);
        if (errors != null && errors.length != 0) {
            Utilities.userAlert(mainScrPane, (Object) errors);
            return false;
        } else {
            modifyParameterOrGene(userObj);
            resetSettings();

            if (!(userObj.info instanceof SubmodelInfo)) {
                final DefaultTreeModel model = (DefaultTreeModel) geneTree.getModel();
                model.nodeStructureChanged(editedNode);
            }

            editedNode = null;

            updateNumberOfGenes();
            enableDisableSettings(false);
            return true;
        }
    }

    //----------------------------------------------------------------------------------------------------
    public boolean closeActiveModification() {
        return editedNode != null ? modify() : true;
    }

    //------------------------------------------------------------------------------
    private void modifyParameterOrGene(final ParameterOrGene param) {
        if (constantRButton.isSelected()) {
            final ParameterInfo info = param.getInfo();
            if (info.isEnum())
                param.setConstant(enumDefBox.getSelectedItem());
            else if (info instanceof MasonChooserParameterInfo)
                param.setConstant(enumDefBox.getSelectedIndex());
            else if (info instanceof SubmodelInfo) {
                final SubmodelInfo sInfo = (SubmodelInfo) info;
                modifySubmodelParameterInfo(sInfo);
            } else if (info.isFile())
                param.setConstant(ParameterInfo.getValue(fileTextField.getToolTipText(), info.getType()));
            else
                param.setConstant(ParameterInfo.getValue(constantField.getText().trim(), info.getType()));
        } else if (intGeneValueRangeRButton.isSelected()) {
            final Long minValue = new Long(intMinField.getText().trim());
            final Long maxValue = new Long(intMaxField.getText().trim());
            param.setGene(minValue, maxValue);
        } else if (doubleGeneValueRangeRButton.isSelected()) {
            final Double minValue = new Double(doubleMinField.getText().trim());
            final Double maxValue = new Double(doubleMaxField.getText().trim());
            param.setGene(minValue, maxValue);
        } else if (listGeneValueRButton.isSelected()) {
            final List<Object> valueList = new ArrayList<Object>();
            String values = valuesArea.getText().trim();
            values = values.replaceAll("\\s+", " ");
            final StringTokenizer tokenizer = new StringTokenizer(values, " ");
            while (tokenizer.hasMoreTokens())
                valueList.add(parseListElement(param.getInfo().getJavaType(), tokenizer.nextToken()));
            param.setGene(valueList);
        }
    }

    //----------------------------------------------------------------------------------------------------
    private void modifySubmodelParameterInfo(final SubmodelInfo sInfo) {
        final Object selectedItem = submodelTypeBox.getSelectedItem();
        if (selectedItem instanceof ClassElement) {
            ClassElement aClassElement = (ClassElement) selectedItem;
            final Class<?> newActualType = aClassElement.clazz;

            if (!parentPage.classEquals(newActualType, sInfo.getActualType())) {
                sInfo.setActualType(newActualType, aClassElement.instance);
                addSubParametersToTree(sInfo, editedNode);
            } // else do nothing
        }
    }

    //----------------------------------------------------------------------------------------------------
    private void addSubParametersToTree(final SubmodelInfo sInfo, final DefaultMutableTreeNode node) {
        try {
            final DefaultTreeModel treeModel = (DefaultTreeModel) geneTree.getModel();

            model.addSubmodelParameter(sInfo, node);

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

    //----------------------------------------------------------------------------------------------------
    private void updateNumberOfGenes() {
        int count = 0;

        final DefaultTreeModel treeModel = (DefaultTreeModel) geneTree.getModel();
        final DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
        @SuppressWarnings("rawtypes")
        final Enumeration nodes = root.breadthFirstEnumeration();
        nodes.nextElement();

        while (nodes.hasMoreElements()) {
            final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement();
            final ParameterOrGene userObj = (ParameterOrGene) node.getUserObject();
            if (userObj.isGene())
                count++;
        }

        numberLabel.setText("<html><b>Number of genes:</b> " + count + "</html>");
    }
}