ai.aitia.meme.paramsweep.gui.Page_ParametersV2.java Source code

Java tutorial

Introduction

Here is the source code for ai.aitia.meme.paramsweep.gui.Page_ParametersV2.java

Source

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

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
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.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import ai.aitia.meme.Logger;
import ai.aitia.meme.events.HybridAction;
import ai.aitia.meme.events.IHybridActionListener;
import ai.aitia.meme.gui.Wizard;
import ai.aitia.meme.gui.Wizard.Button;
import ai.aitia.meme.gui.Wizard.IArrowsInHeader;
import ai.aitia.meme.gui.Wizard.IWizardPage;
import ai.aitia.meme.paramsweep.ParameterSweepWizard;
import ai.aitia.meme.paramsweep.batch.IModelInformation.ModelInformationException;
import ai.aitia.meme.paramsweep.batch.output.RecordableInfo;
import ai.aitia.meme.paramsweep.generator.WizardSettingsManager;
import ai.aitia.meme.paramsweep.gui.component.DefaultJButton;
import ai.aitia.meme.paramsweep.gui.component.ListAsATree;
import ai.aitia.meme.paramsweep.gui.info.AvailableParameter;
import ai.aitia.meme.paramsweep.gui.info.MasonChooserParameterInfo;
import ai.aitia.meme.paramsweep.gui.info.ParameterInATree;
import ai.aitia.meme.paramsweep.gui.info.ParameterInfo;
import ai.aitia.meme.paramsweep.internal.platform.IGUIController;
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.utils.ParameterEnumeration;
import ai.aitia.meme.paramsweep.utils.ParameterParserException;
import ai.aitia.meme.paramsweep.utils.Util;
import ai.aitia.meme.paramsweep.utils.Utilities;
import ai.aitia.meme.paramsweep.utils.WizardLoadingException;
import ai.aitia.meme.utils.FormsUtils;
import ai.aitia.meme.utils.FormsUtils.Separator;
import ai.aitia.meme.utils.GUIUtils;

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

/** This class provides a new version of Parameters page of the Parameter Sweep Wizard. */
public class Page_ParametersV2 implements IWizardPage, IArrowsInHeader, ActionListener, FocusListener {

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

    static final int ICON_WIDTH_AND_HEIGHT = 25;

    private static final ImageIcon PARAMETER_ADD_ICON_DIS = new ImageIcon(
            new ImageIcon(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.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(Page_ParametersV2.class.getResource("icons/remove_box.png")).getImage()
                    .getScaledInstance(ICON_WIDTH_AND_HEIGHT, ICON_WIDTH_AND_HEIGHT, Image.SCALE_SMOOTH));

    private static final ImageIcon EMPTY = new ImageIcon(
            new ImageIcon(Page_ParametersV2.class.getResource("icons/empty.png")).getImage()
                    .getScaledInstance(ICON_WIDTH_AND_HEIGHT, ICON_WIDTH_AND_HEIGHT, Image.SCALE_SMOOTH));

    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_ADD_ENUM = "ADD_ENUM",
            ACTIONCOMMAND_REMOVE_ENUM = "REMOVE_ENUM", ACTIONCOMMAND_NEW_PARAMETERS = "NEW_PARAMETER";

    private static final String TITLE = "Parameters";
    private static final String INFO_TEXT = "Specify input parameter values: Set the number of runs for each parameter value and define the parameter space";
    private static final String ORIGINAL_TEXT = "Select a parameter to modify its settings.";

    /** The owner of the page. */
    private ParameterSweepWizard owner = null;
    /** The list of information objects of the parameters. */
    private List<ParameterInfo> parameters = null;
    /** The names of the parameters. */
    private String[] initParamResult = null;
    /** The names of the parameters of the original model. */
    private String[] originalInitParamResult = null;
    /** The list of information objects of the new (defined by this wizard) parameters. */
    private List<ParameterInfo> newParameters = null;

    private IntelliContext intelliContext = null;
    private boolean modelInformationException = false;

    private final Container container;

    private JLabel runsLabel = new JLabel("Runs: ");
    private JTextField runsField = new JTextField("");
    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<Object> enumDefBox;
    private JList<Object> leftEnumValueList;
    private JList<Object> rightEnumValueList;
    private JButton addEnumButton;
    private JButton removeEnumButton;
    private JButton cancelButton;
    private JButton modifyButton;
    private JTextField fileTextField;
    private JButton browseFileButton = new JButton(FileSystemView.getFileSystemView().getSystemIcon(new File(".")));

    private JLabel editedParameterText;
    private JPanel rightMiddle;

    private JList<AvailableParameter> parameterList;
    private JButton newParameterButton = new JButton("Add new parameters...");
    private JButton newParameterButtonCopy = new JButton("Add new parameters...");

    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;

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

    //----------------------------------------------------------------------------------------------------
    public Page_ParametersV2(final ParameterSweepWizard owner) {
        this.owner = owner;
        container = initContainer();
    }

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

    //----------------------------------------------------------------------------------------------------
    /** {@inheritDoc} 
     */
    @Override
    public Container getPanel() {

        return container;
    }

    //----------------------------------------------------------------------------------------------------
    @SuppressWarnings("serial")
    private Container initContainer() {

        // left
        parameterList = new JList<AvailableParameter>();
        parameterList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        new ListAction<AvailableParameter>(parameterList, new AbstractAction() {
            public void actionPerformed(final ActionEvent event) {
                final AvailableParameter selectedParameter = parameterList.getSelectedValue();
                addParameterToTree(Collections.singletonList(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();
                        enableDisableParameterCombinationButtons();
                    } else
                        parameterList.clearSelection();
                }
            }
        });

        final JScrollPane parameterListPane = new JScrollPane(parameterList);
        parameterListPane.setBorder(BorderFactory.createTitledBorder(null, "Model parameters", TitledBorder.LEADING,
                TitledBorder.BELOW_TOP));
        parameterListPane.setPreferredSize(new Dimension(230, 300));

        final JPanel parametersPanel = FormsUtils
                .build("p:g p", "[DialogBorder]00 f:p:g||" + "_1 p", parameterListPane, newParameterButton)
                .getPanel();
        newParameterButton.setActionCommand("NEW_PARAMETER");
        newParameterButtonCopy.setActionCommand("NEW_PARAMETER");

        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(400, 500));

        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));

        // right
        editedParameterText = new JLabel(ORIGINAL_TEXT);
        editedParameterText.setPreferredSize(new Dimension(250, 40));

        runsField = new JTextField();
        runsField.setActionCommand("RUNS_FIELD");
        runsField.addFocusListener(this);
        if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.GLOBAL)
            runsField.setEnabled(true);

        constDef = new JRadioButton("Constant");
        listDef = new JRadioButton("List");
        incrDef = new JRadioButton("Increment");

        final JPanel rightTop = FormsUtils.build("p ' p:g", "[DialogBorder]00||" + "12||" + "33||" + "44||" + "55",
                editedParameterText, runsLabel, runsField, constDef, listDef, incrDef).getPanel();

        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<Object>(new DefaultComboBoxModel<Object>());
        final JPanel enumDefPanel = FormsUtils
                .build("p ~ p:g", "[DialogBorder]01 p", "Constant value:", CellConstraints.TOP, enumDefBox)
                .getPanel();

        leftEnumValueList = new JList<Object>(new DefaultListModel<Object>());
        rightEnumValueList = new JList<Object>(new DefaultListModel<Object>());
        final JScrollPane leftEnumValuePane = new JScrollPane(leftEnumValueList,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        final JScrollPane rightEnumValuePane = new JScrollPane(rightEnumValueList,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        leftEnumValuePane.setPreferredSize(new Dimension(125, 100));
        rightEnumValuePane.setPreferredSize(new Dimension(125, 100));

        addEnumButton = new DefaultJButton();
        addEnumButton.setOpaque(false);
        addEnumButton.setRolloverEnabled(true);
        addEnumButton.setIcon(PARAMETER_ADD_ICON);
        addEnumButton.setRolloverIcon(PARAMETER_ADD_ICON_RO);
        addEnumButton.setDisabledIcon(PARAMETER_ADD_ICON_DIS);
        addEnumButton.setBorder(null);
        addEnumButton.setBorderPainted(false);
        addEnumButton.setContentAreaFilled(false);
        addEnumButton.setFocusPainted(false);
        addEnumButton.setToolTipText("Add selected value");
        addEnumButton.setActionCommand(ACTIONCOMMAND_ADD_ENUM);

        removeEnumButton = new DefaultJButton();
        removeEnumButton.setOpaque(false);
        removeEnumButton.setRolloverEnabled(true);
        removeEnumButton.setIcon(PARAMETER_REMOVE_ICON);
        removeEnumButton.setRolloverIcon(PARAMETER_REMOVE_ICON_RO);
        removeEnumButton.setDisabledIcon(PARAMETER_REMOVE_ICON_DIS);
        removeEnumButton.setBorder(null);
        removeEnumButton.setBorderPainted(false);
        removeEnumButton.setContentAreaFilled(false);
        removeEnumButton.setFocusPainted(false);
        removeEnumButton.setToolTipText("Remove selected value");
        removeEnumButton.setActionCommand(ACTIONCOMMAND_REMOVE_ENUM);

        final JPanel enumListPanel = FormsUtils
                .build("p:g ~ p ' p ~ p:g", "[DialogBorder]0011 f:p:g||" + "_23_ p||", leftEnumValuePane,
                        rightEnumValuePane, removeEnumButton, addEnumButton)
                .getPanel();

        leftEnumValueList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(final MouseEvent e) {
                if (SwingUtilities.isLeftMouseButton(e) && e.getComponent().isEnabled() && e.getClickCount() == 2) {
                    final DefaultListModel<Object> model = (DefaultListModel<Object>) rightEnumValueList.getModel();

                    for (final Object element : leftEnumValueList.getSelectedValuesList())
                        model.addElement(element);
                }
            }
        });
        rightEnumValueList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(final MouseEvent e) {
                if (SwingUtilities.isLeftMouseButton(e) && e.getComponent().isEnabled() && e.getClickCount() == 2) {
                    final DefaultListModel<Object> model = (DefaultListModel<Object>) rightEnumValueList.getModel();

                    for (final Object element : rightEnumValueList.getSelectedValuesList())
                        model.removeElement(element);
                }
            }
        });

        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());
            }
        });
        browseFileButton.setActionCommand(ACTIONCOMMAND_BROWSE);
        final JPanel fileDefPanel = FormsUtils
                .build("p ~ p:g ~p", "[DialogBorder]012", "File:", fileTextField, browseFileButton).getPanel();

        constDefPanel.setName("CONST");
        listDefPanel.setName("LIST");
        incrDefPanel.setName("INCREMENT");
        enumDefPanel.setName("ENUM");
        enumListPanel.setName("ENUMLIST");
        fileDefPanel.setName("FILE");

        rightMiddle = new JPanel(new CardLayout());
        rightMiddle.add(constDefPanel, constDefPanel.getName());
        rightMiddle.add(listDefPanel, listDefPanel.getName());
        rightMiddle.add(incrDefPanel, incrDefPanel.getName());
        rightMiddle.add(enumDefPanel, enumDefPanel.getName());
        rightMiddle.add(enumListPanel, enumListPanel.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();

        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));

        // the whole paramsweep panel
        final JPanel content = FormsUtils.build("p:g p", "01 f:p:g", left, right).getPanel();

        JPanel sweepPanel = new JPanel();
        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, browseFileButton, runsField,
                newParameterButton, newParameterButtonCopy, addEnumButton, removeEnumButton);

        runsField.setName("fld_wizard_params_runs");
        constDef.setName("rbtn_wizard_params_const");
        listDef.setName("rbtn_wizard_params_list");
        incrDef.setName("rbtn_wizard_params_incr");
        modifyButton.setName("btn_wizard_params_modify");
        cancelButton.setName("btn_wizard_params_cancel");
        incrStartValueField.setName("fld_wizard_params_incrstart");
        incrEndValueField.setName("fld_wizard_params_incrend");
        incrStepField.setName("fld_wizard_params_incrstep");
        constDefField.setName("fld_wizard_params_constval");
        listDefArea.setName("fld_wizard_params_paramlist");
        newParameterButton.setName("btn_wizard_params_newparameter");
        enumDefBox.setName("cb_wizard_params_enum_const");
        addEnumButton.setName("btn_wizard_params_add_enum_value");
        removeEnumButton.setName("btn_wizard_params_remove_enum_value");
        browseFileButton.setName("btn_wizard_params_browse");
        fileTextField.setName("fld_wizard_params_file_const");
        addNewBoxButton.setName("btn_wizard_params_newbox");

        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 DefaultJButton();
        closeButton.setOpaque(false);
        closeButton.setFocusable(false);
        closeButton.setBorderPainted(false);
        closeButton.setContentAreaFilled(false);
        closeButton.setFocusPainted(false);
        closeButton.setBorder(null);

        if (first) {
            closeButton.setIcon(EMPTY);
            runLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
        } else {
            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 ListAsATree(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;
                            }
                        }
                    }

                    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(250, 250));

        final JButton upButton = new DefaultJButton();
        final JButton downButton = new DefaultJButton();

        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 Separator(""), treeScrPane, upButton, downButton)
                .getPanel();

        mainPanel.setBorder(BorderFactory.createTitledBorder(""));

        final JButton addButton = new DefaultJButton();
        addButton.setRolloverEnabled(true);
        addButton.setIcon(PARAMETER_ADD_ICON);
        addButton.setRolloverIcon(PARAMETER_ADD_ICON_RO);
        addButton.setDisabledIcon(PARAMETER_ADD_ICON_DIS);
        addButton.setBorder(null);
        addButton.setBorderPainted(false);
        addButton.setContentAreaFilled(false);
        addButton.setFocusPainted(false);
        addButton.setToolTipText("Add selected parameter");
        addButton.setActionCommand(ACTIONCOMMAND_ADD_PARAM);

        final JButton removeButton = new DefaultJButton();

        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();

        final ParameterCombinationGUI pcGUI = new ParameterCombinationGUI(tree, treeRoot, runLabel, warningLabel,
                addButton, removeButton, upButton, downButton);
        parameterTreeBranches.add(pcGUI);

        int idx = parameterTreeBranches.size() - 1;
        if (!first)
            closeButton.setName("btn_wizard_params_close_" + idx);
        upButton.setName("btn_wizard_params_moveup_" + idx);
        downButton.setName("btn_wizard_params_movedown_" + idx);
        addButton.setName("btn_wizard_params_addparam_" + idx);
        removeButton.setName("btn_wizard_params_removeparam_" + idx);

        class HybridActionListener implements ActionListener, IHybridActionListener {

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

            //----------------------------------------------------------------------------------------------------
            public void actionPerformed(final ActionEvent e) {
                hybridAction(e, null);
            }

            //----------------------------------------------------------------------------------------------------
            public void hybridAction(ActionEvent e, HybridAction a) {
                String cmd = null;
                if (a != null)
                    cmd = a.getValue(Action.ACTION_COMMAND_KEY).toString();
                else
                    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 List<AvailableParameter> selectedValues = parameterList.getSelectedValuesList();
                if (selectedValues != null && selectedValues.size() > 0) {
                    addParameterToTree(selectedValues, 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(owner, 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 = findMatchedInfo(userObj.info);
                if (originalInfo != null) {
                    final DefaultListModel<AvailableParameter> model = (DefaultListModel<AvailableParameter>) parameterList
                            .getModel();
                    model.addElement(new AvailableParameter(originalInfo));
                    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()));
                    }
                }
            }
        }
        ;

        final HybridActionListener hybridActionListener = new HybridActionListener();
        GUIUtils.addActionListener(hybridActionListener, closeButton, addButton);

        final HybridAction upAction = new HybridAction(hybridActionListener, "Move up", null,
                Action.ACTION_COMMAND_KEY, ACTIONCOMMAND_MOVE_UP);
        final HybridAction downAction = new HybridAction(hybridActionListener, "Move down", null,
                Action.ACTION_COMMAND_KEY, ACTIONCOMMAND_MOVE_DOWN);
        final HybridAction removeAction = new HybridAction(hybridActionListener, "Remove", null,
                Action.ACTION_COMMAND_KEY, ACTIONCOMMAND_REMOVE_PARAM);

        final JPopupMenu contextMenu = new JPopupMenu();
        contextMenu.setName("cmenu_wizard_parameters_treecmenu_" + idx);
        contextMenu.add(upAction);
        contextMenu.add(downAction);
        contextMenu.add(removeAction);

        contextMenu.getComponent(0).setName("btn_wizard_params_cmenumoveup_" + idx);
        contextMenu.getComponent(1).setName("btn_wizard_params_cmenumovedown_" + idx);
        contextMenu.getComponent(2).setName("btn_wizard_params_cmenuremove_" + idx);

        tree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                if (SwingUtilities.isRightMouseButton(e) && e.getComponent().isEnabled()) {
                    DefaultMutableTreeNode node = mouseOnNode(tree, e);
                    if (node == null)
                        node = (DefaultMutableTreeNode) tree.getPathForRow(tree.getRowCount() - 1)
                                .getLastPathComponent();
                    tree.setSelectionPath(new TreePath(node.getPath()));
                    contextMenu.show(e.getComponent(), e.getX(), e.getY());
                }
            }
        });

        upButton.setAction(upAction);
        upButton.setOpaque(false);
        upButton.setRolloverEnabled(true);
        upButton.setText(""); // need to delete the text explicitly because the button inherits text from the action
        upButton.setIcon(PARAMETER_UP_ICON);
        upButton.setRolloverIcon(PARAMETER_UP_ICON_RO);
        upButton.setDisabledIcon(PARAMETER_UP_ICON_DIS);
        upButton.setBorder(null);
        upButton.setBorderPainted(false);
        upButton.setContentAreaFilled(false);
        upButton.setFocusPainted(false);
        upButton.setToolTipText("Move up the selected parameter");

        downButton.setAction(downAction);
        downButton.setOpaque(false);
        downButton.setRolloverEnabled(true);
        downButton.setText(""); // need to delete the text explicitly because the button inherits text from the action
        downButton.setIcon(PARAMETER_DOWN_ICON);
        downButton.setRolloverIcon(PARAMETER_DOWN_ICON_RO);
        downButton.setDisabledIcon(PARAMETER_DOWN_ICON_DIS);
        downButton.setBorder(null);
        downButton.setBorderPainted(false);
        downButton.setContentAreaFilled(false);
        downButton.setFocusPainted(false);
        downButton.setToolTipText("Move down the selected parameter");

        removeButton.setAction(removeAction);
        removeButton.setOpaque(false);
        removeButton.setRolloverEnabled(true);
        removeButton.setText(""); // need to delete the text explicitly because the button inherits text from the action
        removeButton.setIcon(PARAMETER_REMOVE_ICON);
        removeButton.setRolloverIcon(PARAMETER_REMOVE_ICON_RO);
        removeButton.setDisabledIcon(PARAMETER_REMOVE_ICON_DIS);
        removeButton.setBorder(null);
        removeButton.setBorderPainted(false);
        removeButton.setContentAreaFilled(false);
        removeButton.setFocusPainted(false);
        removeButton.setToolTipText("Remove selected parameter");

        result.setPreferredSize(new Dimension(300, 250));
        enableDisableParameterCombinationButtons();

        return result;
    }

    //----------------------------------------------------------------------------------------------------
    /** Returns the node that belongs to the location of the event. */
    private DefaultMutableTreeNode mouseOnNode(final JTree tree, final MouseEvent event) {
        Point loc = event.getPoint();
        TreePath path = null;
        for (int i = 20; path == null && i <= loc.x; path = tree.getPathForLocation(i, loc.y), i += 20)
            ;
        if (path != null)
            return (DefaultMutableTreeNode) path.getLastPathComponent();
        return null;
    }

    //----------------------------------------------------------------------------------------------------
    private void addParameterToTree(final List<AvailableParameter> parameters,
            final ParameterCombinationGUI pcGUI) {
        final DefaultListModel<AvailableParameter> listModel = (DefaultListModel<AvailableParameter>) 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));
            treeModel.insertNodeInto(newNode, root, root.getChildCount());
        }

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

    //----------------------------------------------------------------------------------------------------
    public void resetParamsweepGUI() {
        changeText(null, null);
        if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.LOCAL)
            runsField.setText("");
        constDef.setSelected(true);
        constDefField.setText(null);
        incrStartValueField.setText(null);
        incrEndValueField.setText(null);
        incrStepField.setText(null);
        listDefArea.setText(null);
        fileTextField.setText(null);
        fileTextField.setToolTipText(null);
        leftEnumValueList.setModel(new DefaultListModel<Object>());
        rightEnumValueList.setModel(new DefaultListModel<Object>());
        combinationsPanel.removeAll();
        parameterTreeBranches.clear();
        combinationsPanel.add(createAParameterBox(true));
        combinationsPanel.revalidate();
    }

    //----------------------------------------------------------------------------------------------------
    /** {@inheritDoc} 
     */
    @Override
    public boolean isEnabled(final Button b) {
        if (modelInformationException && (b == Button.NEXT || b == Button.FINISH))
            return false;
        return PlatformSettings.isEnabledForPageParameters(owner, b);
    }

    //----------------------------------------------------------------------------------------------------
    /** {@inheritDoc} 
     */
    public boolean onButtonPress(final Button b) {
        boolean enabled = isEnabled(b);
        if (enabled) {
            if (b == Button.CANCEL)
                return true;
            if (editedNode == null || modify()) {
                String invalidInfoName = checkInfos();
                if (invalidInfoName != null) {
                    Utilities.userAlert(owner, "Please specify a file for parameter " + invalidInfoName);
                    return false;
                }

                return true;
            }
        }
        return false;
    }

    //----------------------------------------------------------------------------------------------------
    public void focusGained(FocusEvent e) {
    }

    //----------------------------------------------------------------------------------------------------
    public void focusLost(FocusEvent e) {
        if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.GLOBAL)
            updateNumberOfRuns();
    }

    //----------------------------------------------------------------------------------------------------
    /** {@inheritDoc} 
     */
    public void onPageChange(boolean show) {
        if (show) {
            if (owner.getModelState() == ParameterSweepWizard.ERROR)
                return;
            initializePageForPlatform();
            if (owner.getModelState() == ParameterSweepWizard.NEW_MODEL) {
                modelInformationException = false;
                resetParamsweepGUI();
                parameters = createParameters();
                if (parameters == null)
                    return;
                if (owner.getParameterFile() != null && owner.getParameterFile().exists()) {
                    try {
                        final DefaultMutableTreeNode root = PlatformSettings.parseParameterFile(parameters,
                                owner.getParameterFile());
                        setGlobalRunsField(root);
                        initializePageFromTree(root);
                    } catch (ParameterParserException | WizardLoadingException e) {
                        Utilities.userAlert(owner, "Cannot initialize from the defined parameter file.",
                                "Reason: " + Util.getLocalizedMessage(e));
                        e.printStackTrace(ParameterSweepWizard.getLogStream());
                        createDefaultParameterList(parameters);
                        ;
                    }
                } else
                    createDefaultParameterList(parameters);
                enableDisableSettings(false);
                modifyButton.setEnabled(false);
                owner.setModelState(ParameterSweepWizard.NEW_RECORDERS);
            }
            if (owner.getParameterFile() != null && owner.isParameterFileChanged()) {
                if (owner.getModelState() != ParameterSweepWizard.NEW_MODEL && owner.getParameterFile().exists()) {
                    try {
                        final DefaultMutableTreeNode root = PlatformSettings.parseParameterFile(parameters,
                                owner.getParameterFile());
                        setGlobalRunsField(root);
                        initializePageFromTree(root);
                    } catch (ParameterParserException | WizardLoadingException e) {
                        Utilities.userAlert(owner, "Cannot initialize from the defined parameter file.",
                                "Reason: " + Util.getLocalizedMessage(e));
                        e.printStackTrace(ParameterSweepWizard.getLogStream());
                    }
                }
            }
            owner.setParameterFileChanged(false);
            updateNumberOfRuns();
        } else {
            if (cancelButton.isEnabled())
                cancelButton.doClick();
        }
    }

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

    //-------------------------------------------------------------------------------
    /** Loads the page-related model settings from the XML element <code>element</code>. This
     *  method is part of the model settings retrieving performed by {@link ai.aitia.meme.paramsweep.generator.WizardSettingsManager 
     *  WizardSettingsManager}.
     * @throws WizardLoadingException if the XML document is invalid
     */
    public void load(Element element) throws WizardLoadingException {
        NodeList nl = element.getElementsByTagName(WizardSettingsManager.NEW_PARAMETERS);
        if (nl == null || nl.getLength() == 0)
            newParameters = null;
        else {
            NodeList nodes = ((Element) nl.item(0)).getElementsByTagName(WizardSettingsManager.PARAMETER);
            if (nodes == null || nodes.getLength() == 0)
                throw new WizardLoadingException(true, "missing node: " + WizardSettingsManager.PARAMETER);
            newParameters = new ArrayList<ParameterInfo>(nodes.getLength());
            for (int i = 0; i < nodes.getLength(); ++i) {
                Element param = (Element) nodes.item(i);
                String type = param.getAttribute(WizardSettingsManager.TYPE);
                if (type == null || type.equals(""))
                    throw new WizardLoadingException(true,
                            "missing 'type' attribute at node: " + WizardSettingsManager.PARAMETER);
                String javaTypeStr = param.getAttribute(WizardSettingsManager.JAVA_TYPE);
                if (javaTypeStr == null || "".equals(javaTypeStr))
                    throw new WizardLoadingException(true,
                            "missing 'java_type' attribute at node: " + WizardSettingsManager.PARAMETER);
                NodeList content = param.getChildNodes();
                if (content == null || content.getLength() == 0)
                    throw new WizardLoadingException(true,
                            "missing content at node: " + WizardSettingsManager.PARAMETER);
                String name = ((Text) content.item(0)).getNodeValue();
                Class<?> javaType = null;
                try {
                    javaType = Utilities.toClass(owner.getClassLoader(), javaTypeStr);
                } catch (ClassNotFoundException e) {
                    throw new WizardLoadingException(true, "invalid type at parameter: " + name);
                }
                ParameterInfo pi = new ParameterInfo(name, type, javaType);
                if (!pi.isNumeric() && !pi.isBoolean() && !pi.getType().equals("String"))
                    throw new WizardLoadingException(true,
                            "invalid 'type' attribute at node: " + WizardSettingsManager.PARAMETER);
                pi.setInitValue();
                pi.setRuns(1);
                newParameters.add(pi);
            }
        }

        resetParamsweepGUI();
        parameters = createParameters();

        nl = null;
        nl = element.getElementsByTagName(WizardSettingsManager.PARAMETER_FILE);
        if (nl == null || nl.getLength() == 0)
            throw new WizardLoadingException(true, "missing node: " + WizardSettingsManager.PARAMETER_FILE);
        NodeList content = nl.item(0).getChildNodes();
        if (content == null || content.getLength() == 0)
            throw new WizardLoadingException(true,
                    "missing content at node: " + WizardSettingsManager.PARAMETER_FILE);
        String paramFileContent = ((Text) content.item(0)).getNodeValue();
        DefaultMutableTreeNode root = null;
        try {
            root = PlatformSettings.parseParameterFile(parameters, paramFileContent);
            initializePageFromTree(root);
        } catch (ParameterParserException e) {
            throw new WizardLoadingException(true, e);
        }
        if (cancelButton.isEnabled())
            cancelButton.doClick();
        setGlobalRunsField(root);
        updateNumberOfRuns();
    }

    //-------------------------------------------------------------------------------
    /** Saves the page-related model settings to the XML node <code>node</code>. This
     *  method is part of the model settings storing performed by {@link ai.aitia.meme.paramsweep.generator.WizardSettingsManager 
     *  WizardSettingsManager}.
     * @throws TransformerException 
     * @throws ParserConfigurationException 
     */
    public void save(Node node) throws ParserConfigurationException, TransformerException {
        final Document document = node.getOwnerDocument();

        Element element = document.createElement(WizardSettingsManager.PARAMETER_FILE);
        element.appendChild(document
                .createTextNode(PlatformSettings.generateParameterTreeOutput(createTreeFromParameterPage())));
        node.appendChild(element);

        if (newParameters != null) {
            Element np = document.createElement(WizardSettingsManager.NEW_PARAMETERS);
            for (ParameterInfo pi : newParameters) {
                element = document.createElement(WizardSettingsManager.PARAMETER);
                element.setAttribute(WizardSettingsManager.TYPE, pi.getType());
                element.setAttribute(WizardSettingsManager.JAVA_TYPE, pi.getJavaType().getName());
                String name = pi.getName();
                final RecordableInfo dummy = new RecordableInfo(name, Integer.TYPE, null, name);
                try {
                    if (owner.getModelInformation().getRecordables().indexOf(dummy) == -1)
                        name = Util.uncapitalize(name);
                } catch (ModelInformationException e) {
                    throw new IllegalStateException(e);
                }
                element.appendChild(document.createTextNode(name));
                np.appendChild(element);
            }
            node.appendChild(np);
        }
    }

    //----------------------------------------------------------------------------------------------------
    public String[] getInitParamResult() {
        return initParamResult;
    }

    public List<ParameterInfo> getNewParametersList() {
        return newParameters;
    }

    public List<ParameterInfo> getParameters() {
        return parameters;
    }

    //------------------------------------------------------------------------------
    public IIntelliContext getIntelliContext() {
        if (intelliContext == null)
            intelliContext = new IntelliContext();
        return intelliContext;
    }

    //------------------------------------------------------------------------------
    /** Creates the list of information objects of parameters. */
    private List<ParameterInfo> createParameters() {
        try {
            batchParameters = owner.getModelInformation().getParameters();
        } catch (ModelInformationException e) {
            Utilities.userAlert(owner, "Identification of parameters is failed:", Util.getLocalizedMessage(e));
            modelInformationException = true;
            owner.enableDisableButtons();
            owner.setModelState(ParameterSweepWizard.ERROR);
            e.printStackTrace(ParameterSweepWizard.getLogStream());
            return null;
        }
        originalInitParamResult = new String[batchParameters.size()];
        for (int i = 0; i < batchParameters.size(); ++i)
            originalInitParamResult[i] = batchParameters.get(i).getName();
        List<ParameterInfo> info = new ArrayList<ParameterInfo>();
        for (ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?> parameter : batchParameters) {
            ParameterInfo pi = InfoConverter.parameterInfo2ParameterInfo(parameter);
            if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.LOCAL)
                pi.setRuns(1);
            pi.setDefinitionType(ParameterInfo.CONST_DEF);
            pi.setValue(parameter.getDefaultValue());
            info.add(pi);

        }
        if (newParameters != null) {
            initParamResult = new String[originalInitParamResult.length + newParameters.size()];
            for (int i = 0; i < originalInitParamResult.length; ++i)
                initParamResult[i] = originalInitParamResult[i];
            for (int i = 0; i < newParameters.size(); ++i) {
                String name = newParameters.get(i).getName();
                initParamResult[originalInitParamResult.length + i] = name;
                newParameters.get(i).setName(Util.capitalize(name));
                info.add(newParameters.get(i).clone());
            }
            //         info.addAll(newParameters);
        } else
            initParamResult = originalInitParamResult;
        Collections.sort(info);
        return info;
    }

    //------------------------------------------------------------------------------
    /** Builds the parameter list on the gui from the <code>parameters</code> list. */
    private void createDefaultParameterList(final List<ParameterInfo> parameters) {
        final DefaultListModel<AvailableParameter> model = new DefaultListModel<>();
        for (final ParameterInfo parameterInfo : parameters)
            model.addElement(new AvailableParameter(parameterInfo));
        parameterList.setModel(model);
        if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.GLOBAL)
            runsField.setText("1");
    }

    //------------------------------------------------------------------------------
    /** 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 (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.LOCAL)
            runsField.setText(String.valueOf(info.getRuns()));
        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(true);
                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<Object> model = (DefaultComboBoxModel<Object>) 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:
            if (info.isEnum() || info instanceof MasonChooserParameterInfo) {
                view = "ENUMLIST";
                listDef.setSelected(true);
                incrDef.setEnabled(false);
                constDef.setEnabled(true);
                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 DefaultListModel<Object> leftEnumModel = (DefaultListModel<Object>) leftEnumValueList
                        .getModel();
                leftEnumModel.removeAllElements();
                for (final Object object : elements)
                    leftEnumModel.addElement(object);

                final DefaultListModel<Object> rightEnumModel = (DefaultListModel<Object>) rightEnumValueList
                        .getModel();
                rightEnumModel.removeAllElements();
                for (final Object object : info.getValues()) {
                    if (info.isEnum())
                        rightEnumModel.addElement(object);
                    else {
                        final MasonChooserParameterInfo chooserInfo = (MasonChooserParameterInfo) info;
                        rightEnumModel.addElement(chooserInfo.getValidStrings()[(Integer) object]);
                    }
                }
            } else {
                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.isFile()) {
            incrDef.setEnabled(false);
            listDef.setEnabled(false);
        }
        modifyButton.setEnabled(true);
    }

    //------------------------------------------------------------------------------
    /** 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");
            final String humanName = name;
            editedParameterText.setText("<html><b>" + humanName + "</b>: " + type + "</html>");
        }
    }

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

        final String[] errors = checkInput(userObj.info);
        if (errors != null && errors.length != 0) {
            Utilities.userAlert(container, (Object) errors);
            return false;
        } else {
            modifyParameterInfo(userObj.info);
            resetSettings();
            modifyButton.setEnabled(false);
            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 (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.LOCAL) {
            final boolean allowEmptyRun = constDef.isSelected();
            if (runsField.getText().trim().equals("") && !allowEmptyRun)
                errors.add("'Runs' cannot be empty.");
            else if (!runsField.getText().trim().equals("")) {
                try {
                    long i = new Long(runsField.getText().trim()).longValue();
                    if (i <= 0)
                        throw new NumberFormatException();
                } catch (NumberFormatException e) {
                    errors.add("'Runs' must be a positive integer.");
                }
            }
        }
        if (constDef.isSelected()) {
            if (info.isEnum() || info instanceof MasonChooserParameterInfo) {
                // well, the combo box must contain a valid value
            } else if (info.isFile()) {
                if (fileTextField.getText().trim().isEmpty())
                    Logger.logWarning("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()) {
            if (info.isEnum() || info instanceof MasonChooserParameterInfo) {
                final ListModel<Object> model = rightEnumValueList.getModel();
                if (model.getSize() == 0)
                    errors.add("The list on the right cannot be empty.");
            } else {
                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()));
                    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>. */
    private 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 = 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) {
        runsField.setEnabled(
                enabled || PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.GLOBAL);
        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);
        leftEnumValueList.setEnabled(enabled);
        rightEnumValueList.setEnabled(enabled);
        addEnumButton.setEnabled(enabled);
        removeEnumButton.setEnabled(enabled);
        fileTextField.setEnabled(enabled);
        browseFileButton.setEnabled(enabled);
        cancelButton.setEnabled(enabled);
        newParameterButton
                .setEnabled(PlatformSettings.getGUIControllerForPlatform().isNewParametersEnabled() && !enabled);
    }

    //------------------------------------------------------------------------------
    /** Resets the parameter editing related components. */
    private void resetSettings() {
        changeText(null, null);
        if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.LOCAL)
            runsField.setText("");
        constDefField.setText("");
        listDefArea.setText("");
        incrStartValueField.setText("");
        incrEndValueField.setText("");
        incrStepField.setText("");
        fileTextField.setText("");
        fileTextField.setToolTipText("");
        leftEnumValueList.setModel(new DefaultListModel<Object>());
        rightEnumValueList.setModel(new DefaultListModel<Object>());
        constDef.setSelected(true);
        final CardLayout cl = (CardLayout) rightMiddle.getLayout();
        cl.show(rightMiddle, "CONST");
    }

    //------------------------------------------------------------------------------
    /** 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();
        if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.LOCAL) {
            if (runsField.getText().trim().equals("")) {
                if (constDef.isSelected())
                    info.setRuns(1);
                else
                    throw new IllegalStateException("Runs field is empty.");
            } else {
                long i = Long.parseLong(runsField.getText().trim());
                info.setRuns(i);
            }
        }

        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.isFile()) {
                info.setValue(ParameterInfo.getValue(fileTextField.getToolTipText(), info.getType()));
            } else {
                info.setValue(ParameterInfo.getValue(constDefField.getText().trim(), info.getType()));
            }

            break;
        }
        case ParameterInfo.LIST_DEF: {
            if (info.isEnum()) {
                final DefaultListModel<Object> model = (DefaultListModel<Object>) rightEnumValueList.getModel();
                List<Object> result = new ArrayList<Object>();
                for (int i = 0; i < model.size(); result.add(model.get(i++)))
                    ;
                info.setValues(result);
            } else if (info instanceof MasonChooserParameterInfo) {
                final MasonChooserParameterInfo chooserInfo = (MasonChooserParameterInfo) info;
                final String[] validStrings = chooserInfo.getValidStrings();
                List<Object> result = new ArrayList<Object>();
                final DefaultListModel<Object> model = (DefaultListModel<Object>) rightEnumValueList.getModel();
                for (int i = 0; i < model.size(); ++i) {
                    int idx = -1;
                    for (int j = 0; j < validStrings.length; ++j) {
                        if (validStrings[j].equals(model.get(i))) {
                            idx = j;
                            break;
                        }
                    }

                    if (idx >= 0)
                        result.add(idx);
                }
                info.setValues(result);
            } else {
                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;
        }
    }

    //----------------------------------------------------------------------------------------------------
    @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")) {
            final DefaultMutableTreeNode node = editedNode;
            final ParameterInATree userObj = (ParameterInATree) node.getUserObject();
            final CardLayout cl = (CardLayout) rightMiddle.getLayout();
            if (userObj.info instanceof MasonChooserParameterInfo || userObj.info.isEnum()) {
                Object[] elements = null;
                if (userObj.info.isEnum()) {
                    @SuppressWarnings("unchecked")
                    final Class<Enum<?>> type = (Class<Enum<?>>) userObj.info.getJavaType();
                    elements = type.getEnumConstants();
                } else {
                    final MasonChooserParameterInfo chooserInfo = (MasonChooserParameterInfo) userObj.info;
                    elements = chooserInfo.getValidStrings();
                }
                final DefaultComboBoxModel<Object> model = (DefaultComboBoxModel<Object>) enumDefBox.getModel();
                model.removeAllElements();
                for (final Object object : elements) {
                    model.addElement(object);
                }
                if (userObj.info.isEnum())
                    enumDefBox.setSelectedItem(userObj.info.getValue());
                else
                    enumDefBox.setSelectedIndex((Integer) userObj.info.getValue());
                cl.show(rightMiddle, "ENUM");
            } else
                cl.show(rightMiddle, "CONST");
        } else if (command.equals("LIST")) {
            final DefaultMutableTreeNode node = editedNode;
            final ParameterInATree userObj = (ParameterInATree) node.getUserObject();
            final CardLayout cl = (CardLayout) rightMiddle.getLayout();
            if (userObj.info instanceof MasonChooserParameterInfo || userObj.info.isEnum()) {
                Object[] elements = null;
                if (userObj.info.isEnum()) {
                    @SuppressWarnings("unchecked")
                    final Class<Enum<?>> type = (Class<Enum<?>>) userObj.info.getJavaType();
                    elements = type.getEnumConstants();
                } else {
                    final MasonChooserParameterInfo chooserInfo = (MasonChooserParameterInfo) userObj.info;
                    elements = chooserInfo.getValidStrings();
                }

                final DefaultListModel<Object> leftEnumModel = (DefaultListModel<Object>) leftEnumValueList
                        .getModel();
                leftEnumModel.removeAllElements();
                for (final Object object : elements)
                    leftEnumModel.addElement(object);

                final DefaultListModel<Object> rightEnumModel = (DefaultListModel<Object>) rightEnumValueList
                        .getModel();
                rightEnumModel.removeAllElements();
                for (final Object object : userObj.info.getValues()) {
                    if (userObj.info.isEnum())
                        rightEnumModel.addElement(object);
                    else {
                        final MasonChooserParameterInfo chooserInfo = (MasonChooserParameterInfo) userObj.info;
                        rightEnumModel.addElement(chooserInfo.getValidStrings()[(Integer) object]);
                    }
                }
                cl.show(rightMiddle, "ENUMLIST");
            } else
                cl.show(rightMiddle, "LIST");
        } else if (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_ADD_ENUM.equals(command)) {
            final DefaultListModel<Object> model = (DefaultListModel<Object>) rightEnumValueList.getModel();

            for (final Object element : leftEnumValueList.getSelectedValuesList())
                model.addElement(element);

            leftEnumValueList.clearSelection();
        } else if (ACTIONCOMMAND_REMOVE_ENUM.equals(command)) {
            final DefaultListModel<Object> model = (DefaultListModel<Object>) rightEnumValueList.getModel();

            for (final Object element : rightEnumValueList.getSelectedValuesList())
                model.removeElement(element);
        } else if (ACTIONCOMMAND_BROWSE.equals(command))
            chooseFile();
        else if (ACTIONCOMMAND_NEW_PARAMETERS.equals(command)) {
            int result = Utilities.askUser(owner, false, "Warning",
                    "All user defined parameter settings will be lost.", "Do you want to continue?");
            if (result == 1) { // yes
                List<RecordableInfo> candidates = null;
                try {
                    candidates = owner.getModelInformation().getRecordables();
                } catch (ModelInformationException e1) {
                    Utilities.userAlert(owner, "Error while collecting new parameter candidates.",
                            "Reason: " + Util.getLocalizedMessage(e1));
                    e1.printStackTrace(ParameterSweepWizard.getLogStream());
                    return;
                }
                NewParametersDialog dialog = new NewParametersDialog(ParameterSweepWizard.getFrame(), candidates,
                        originalInitParamResult);
                result = dialog.showDialog();
                if (result == NewParametersDialog.OK_OPTION) {
                    List<ParameterInfo> oldNewParameters = newParameters == null ? new ArrayList<ParameterInfo>()
                            : newParameters;
                    newParameters = dialog.getNewParameterList();
                    if (newParameters.size() == 0)
                        newParameters = null;
                    resetParamsweepGUI();
                    parameters = createParameters();
                    if (owner.getParameterFile() != null && owner.getParameterFile().exists()) {
                        try {
                            final DefaultMutableTreeNode root = PlatformSettings.parseParameterFile(parameters,
                                    owner.getParameterFile());
                            setGlobalRunsField(root);
                            initializePageFromTree(root);
                        } catch (ParameterParserException | WizardLoadingException e1) {
                            createDefaultParameterList(parameters);
                            Utilities.userAlert(owner, "Cannot initialize from the defined parameter file.",
                                    "Reason: " + Util.getLocalizedMessage(e1));
                            e1.printStackTrace(ParameterSweepWizard.getLogStream());
                        }
                    } else
                        createDefaultParameterList(parameters);
                    enableDisableSettings(false);
                    modifyButton.setEnabled(false);
                    owner.reinitializeRecordableLists(newParameters == null ? oldNewParameters
                            : Utilities.listSubtract(oldNewParameters, newParameters));
                    owner.cleanRecorders();
                    updateNumberOfRuns();
                }
            }
        }

    }

    //----------------------------------------------------------------------------------------------------
    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()
                        : ParameterSweepWizard.getLastDir().getPath());
        if (!"".equals(fileTextField.getToolTipText()))
            fileDialog.setSelectedFile(new File(fileTextField.getToolTipText()));
        int dialogResult = fileDialog.showOpenDialog(container);
        if (dialogResult == JFileChooser.APPROVE_OPTION) {
            final File selectedFile = fileDialog.getSelectedFile();
            if (selectedFile != null) {
                ParameterSweepWizard.setLastDir(selectedFile.getAbsoluteFile().getParentFile());
                fileTextField.setText(selectedFile.getName());
                fileTextField.setToolTipText(selectedFile.getAbsolutePath());
            }
        }
    }

    //----------------------------------------------------------------------------------------------------
    private void cancelAllSelectionBut(JComponent exception) {
        if (exception != parameterList)
            parameterList.clearSelection();

        for (final ParameterCombinationGUI pGUI : parameterTreeBranches) {
            if (exception != pGUI.tree)
                pGUI.tree.setSelectionPath(null);
        }
    }

    //----------------------------------------------------------------------------------------------------
    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(1);
                return converted;
            }
        }

        return null;
    }

    //----------------------------------------------------------------------------------------------------
    private ParameterInfo findMatchedInfo(final ParameterInfo info) {
        ParameterInfo result = findOriginalInfo(info);

        if (result == null && newParameters != null) {
            for (final ParameterInfo candidate : newParameters) {
                if (info.equals(candidate))
                    return candidate;
            }
        }

        return result;
    }

    //----------------------------------------------------------------------------------------------------
    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.getAction().setEnabled(topLevelSelectionInTheTree);
            pGUI.upButton.getAction().setEnabled(selectionInTheTree);
            pGUI.downButton.getAction().setEnabled(selectionInTheTree);
        }
    }

    //----------------------------------------------------------------------------------------------------
    private String checkInfos() {
        final DefaultListModel<AvailableParameter> listModel = (DefaultListModel<AvailableParameter>) parameterList
                .getModel();
        for (int i = 0; i < listModel.getSize(); ++i) {
            final AvailableParameter param = listModel.get(i);
            final String invalid = 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 = checkFileInfo(userObj);
                if (invalid != null)
                    return invalid;
            }
        }

        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;
    }

    //----------------------------------------------------------------------------------------------------
    public DefaultMutableTreeNode createTreeFromParameterPage() {
        final DefaultMutableTreeNode result = new DefaultMutableTreeNode();

        final DefaultListModel<AvailableParameter> listModel = (DefaultListModel<AvailableParameter>) parameterList
                .getModel();
        for (int i = 0; i < listModel.getSize(); ++i) {
            final AvailableParameter param = listModel.get(i);
            result.add(new DefaultMutableTreeNode(param.info));
        }

        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();
                filterConstants(userObj, result);
            }
        }

        for (final ParameterCombinationGUI pGUI : parameterTreeBranches) {
            final DefaultMutableTreeNode root = pGUI.combinationRoot;
            @SuppressWarnings("rawtypes")
            final Enumeration nodes = root.preorderEnumeration();
            nodes.nextElement(); // root
            DefaultMutableTreeNode parent = result;
            while (nodes.hasMoreElements()) {
                final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement();
                final ParameterInATree userObj = (ParameterInATree) node.getUserObject();
                if (userObj.info.getMultiplicity() > 1) {
                    final DefaultMutableTreeNode parameterNode = new DefaultMutableTreeNode(userObj.info);
                    parent.add(parameterNode);
                    parent = parameterNode;
                }
            }
        }

        return result;
    }

    //----------------------------------------------------------------------------------------------------
    private void initializePageFromTree(DefaultMutableTreeNode paramTree) throws WizardLoadingException {
        final DefaultListModel<AvailableParameter> model = new DefaultListModel<>();
        parameterList.setModel(model);
        boolean useFirstBox = true;
        for (int i = 0; i < paramTree.getChildCount(); ++i) {
            final DefaultMutableTreeNode node = (DefaultMutableTreeNode) paramTree.getChildAt(i);
            final ParameterInfo embeddedInfo = (ParameterInfo) node.getUserObject();

            switch (checkIfConstant(embeddedInfo)) {
            case CONSTANT:
                final ParameterCombinationGUI pcGUI = parameterTreeBranches.get(0);
                final DefaultTreeModel treeModel = (DefaultTreeModel) pcGUI.tree.getModel();
                final DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
                final DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
                        new ParameterInATree(embeddedInfo));
                treeModel.insertNodeInto(newNode, root, root.getChildCount());
                pcGUI.tree.expandPath(new TreePath(treeModel.getPathToRoot(root)));
                break;
            case DEFAULT_CONSTANT:
                model.addElement(new AvailableParameter(embeddedInfo));
                break;
            case NOT_CONSTANT:
                initializeAParameterBox(node, useFirstBox);
                useFirstBox = false;
                break;
            }
        }
    }

    //----------------------------------------------------------------------------------------------------
    private void initializeAParameterBox(final DefaultMutableTreeNode branchRootNode, final boolean useFirstBox) {
        if (!useFirstBox)
            addBox();
        final ParameterCombinationGUI pcGUI = parameterTreeBranches.get(parameterTreeBranches.size() - 1);
        final DefaultTreeModel treeModel = (DefaultTreeModel) pcGUI.tree.getModel();
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();

        @SuppressWarnings("rawtypes")
        final Enumeration nodes = branchRootNode.breadthFirstEnumeration();
        while (nodes.hasMoreElements()) {
            final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement();
            final ParameterInfo info = (ParameterInfo) node.getUserObject();

            final DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(new ParameterInATree(info));
            treeModel.insertNodeInto(newNode, root, root.getChildCount());
            pcGUI.tree.expandPath(new TreePath(treeModel.getPathToRoot(root)));
        }
    }

    //----------------------------------------------------------------------------------------------------
    private ConstantCheckResult checkIfConstant(ParameterInfo info) throws WizardLoadingException {
        if (info.isConstant()) {
            final ParameterInfo originalInfo = findMatchedInfo(info);
            if (originalInfo == null)
                throw new WizardLoadingException(true, "Unknown referenced parameter: " + info.getName());
            return isDefaultConstant(info, originalInfo) ? ConstantCheckResult.DEFAULT_CONSTANT
                    : ConstantCheckResult.CONSTANT;
        }

        return ConstantCheckResult.NOT_CONSTANT;
    }

    //----------------------------------------------------------------------------------------------------
    private boolean isDefaultConstant(final ParameterInfo info, final ParameterInfo defaultValueInfo) {
        if (!info.getJavaType().equals(defaultValueInfo.getJavaType())) {
            throw new IllegalStateException("isDefaultConstant(): Type does not match.");
        }

        if (info.isEnum())
            return info.getValue() == defaultValueInfo.getValue();
        if (info.isBoolean())
            return ((Boolean) info.getValue()).booleanValue() == ((Boolean) defaultValueInfo.getValue())
                    .booleanValue();
        if (info.isNumeric()) {
            final Number num1 = (Number) info.getValue();
            final Number num2 = (Number) defaultValueInfo.getValue();
            return Utilities.numberEquals(num1, num2);
        }

        return info.getValue().equals(defaultValueInfo.getValue());
    }

    //----------------------------------------------------------------------------------------------------
    private void filterConstants(final ParameterInATree paramContainer, final DefaultMutableTreeNode root) {
        if (paramContainer.info.getMultiplicity() == 1) {
            transformToConstant(paramContainer.info);
            root.add(new DefaultMutableTreeNode(paramContainer.info));
        }
    }

    //----------------------------------------------------------------------------------------------------
    private void transformToConstant(final ParameterInfo info) {
        if (info.isConstant())
            return;
        else if (info.getDefinitionType() == ParameterInfo.INCR_DEF) {
            info.setValue(info.getStartValue());
            info.setStartValue(null);
            info.setEndValue(null);
            info.setStep(null);
        }

        info.setDefinitionType(ParameterInfo.CONST_DEF);
    }

    //----------------------------------------------------------------------------------------------------
    private int calculateNumberOfRuns(final DefaultMutableTreeNode combinationRoot) {
        if (combinationRoot.getChildCount() == 0)
            return 0;

        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;

            long run = 1;
            if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.LOCAL
                    && info.getMultiplicity() > 1)
                run = info.getRuns();
            result *= run * info.getMultiplicity();
        }

        if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.GLOBAL)
            result *= parseGlobalRuns();

        return result;
    }

    //----------------------------------------------------------------------------------------------------
    private long parseGlobalRuns() {
        long runs = 1;
        final String runsStr = runsField.getText().trim();
        if (runsStr != null && runsStr.length() > 0) {
            try {
                runs = Long.parseLong(runsStr);
            } catch (NumberFormatException e) {
            }
        }
        return runs;
    }

    //----------------------------------------------------------------------------------------------------
    public void setRunsIfNeccessary(final DefaultMutableTreeNode root) {
        long runs = 1;
        if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.GLOBAL)
            runs = parseGlobalRuns();
        ParameterEnumeration pe = new ParameterEnumeration(root);
        while (pe.hasMoreElements()) {
            DefaultMutableTreeNode node = pe.nextElement();
            if (root.equals(node))
                continue;
            ParameterInfo info = (ParameterInfo) node.getUserObject();
            info.setRuns(runs);
        }
    }

    //----------------------------------------------------------------------------------------------------
    public void transformIncrementsIfNeed(final DefaultMutableTreeNode root) {
        ParameterEnumeration pe = new ParameterEnumeration(root);
        for (DefaultMutableTreeNode node = pe.nextElement(); pe.hasMoreElements(); node = pe.nextElement()) {
            if (root.equals(node))
                continue;
            ParameterInfo info = (ParameterInfo) node.getUserObject();
            if (info.getDefinitionType() == ParameterInfo.INCR_DEF)
                info.transformIfNeed();
        }
    }

    //----------------------------------------------------------------------------------------------------
    private void initializePageForPlatform() {
        IGUIController controller = PlatformSettings.getGUIControllerForPlatform();
        newParameterButton.setEnabled(controller.isNewParametersEnabled());
        newParameterButtonCopy.setEnabled(controller.isNewParametersEnabled());
        newParameterButton.setVisible(controller.isNewParametersEnabled());
        newParameterButtonCopy.setVisible(controller.isNewParametersEnabled());

        switch (controller.getRunOption()) {
        case NONE:
            runsLabel.setVisible(false);
            runsField.setVisible(false);
            break;
        case GLOBAL:
            runsLabel.setText("Runs (global): ");
        default: // do nothing
        }
    }

    //----------------------------------------------------------------------------------------------------
    private void setGlobalRunsField(DefaultMutableTreeNode root) {
        if (PlatformSettings.getGUIControllerForPlatform().getRunOption() == RunOption.GLOBAL) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) root.getChildAt(0);
            if (node != null) {
                ParameterInfo pi = (ParameterInfo) node.getUserObject();
                if (pi != null)
                    runsField.setText(String.valueOf(pi.getRuns()));
            }
        }
    }

    //----------------------------------------------------------------------------------------------------
    public JButton getNewParametersButton() {
        return newParameterButtonCopy;
    }

    //====================================================================================================
    // nested classes

    //----------------------------------------------------------------------------------------------------
    private class IntelliContext extends HashMap<Object, Object> implements IIntelliContext {
        {
            put("scriptSupport", owner.getRecordersPage().getScriptSupport());
        }
        private static final long serialVersionUID = -7383965550748377433L;

        public List<ParameterInfo> getParameters() {
            return parameters;
        }

        public DefaultMutableTreeNode getParameterTreeRootNode() {
            return createTreeFromParameterPage();
        }

        public JButton getNewParametersButton() {
            return Page_ParametersV2.this.getNewParametersButton();
        }

        public File getPluginResourcesDirectory() {
            return new File(System.getProperty("user.dir") + "/resources/Plugins");
        }
    }

    //----------------------------------------------------------------------------------------------------
    private enum ConstantCheckResult {
        CONSTANT, DEFAULT_CONSTANT, NOT_CONSTANT;
    }
}