/*
* Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
* Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* This file is part of Jalview.
*
* Jalview 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.
*
* Jalview 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 Jalview. If not, see .
* The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.gui;
import jalview.bin.Cache;
import jalview.io.DataSourceType;
import jalview.io.FileLoader;
import jalview.io.JalviewFileChooser;
import jalview.io.JalviewFileView;
import jalview.util.MessageManager;
import jalview.ws.jws2.dm.JabaOption;
import jalview.ws.params.ArgumentI;
import jalview.ws.params.OptionI;
import jalview.ws.params.ParameterI;
import jalview.ws.params.ValueConstrainI;
import jalview.ws.params.ValueConstrainI.ValueType;
import jalview.ws.params.simple.FileParameter;
import jalview.ws.params.simple.LogarithmicParameter;
import jalview.ws.params.simple.RadioChoiceParameter;
import jalview.ws.params.simple.StringParameter;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
/**
* GUI generator/manager for options and parameters. Originally abstracted from
* the WsJobParameters dialog box.
*
* @author jprocter
*
*/
public class OptsAndParamsPage
{
public static final int PARAM_WIDTH = 340;
public static final int PARAM_HEIGHT = 150;
public static final int PARAM_CLOSEDHEIGHT = 80;
URL linkImageURL = getClass().getResource("/images/link.gif");
Map optSet = new LinkedHashMap<>();
Map paramSet = new LinkedHashMap<>();
/*
* compact or verbose style parameters
*/
boolean compact = false;
OptsParametersContainerI poparent;
/**
* A class that models a panel rendering a single option (checkbox or choice
* list)
*/
public class OptionBox extends JPanel
implements MouseListener, ActionListener
{
JCheckBox enabled;
final URL finfo;
boolean hasLink = false;
boolean initEnabled = false;
String initVal = null;
OptionI option;
JComboBox val;
/**
* Constructs and adds labels and controls to the panel for one Option
*
* @param opt
*/
public OptionBox(OptionI opt)
{
option = opt;
setLayout(new FlowLayout(FlowLayout.LEFT));
enabled = new JCheckBox(opt.getLabel());
enabled.setSelected(opt.isRequired());
/*
* If option is required, show a label, if optional a checkbox
* (but not for Jabaws pending JWS-126 resolution)
*/
if (opt.isRequired() && !(opt instanceof JabaOption))
{
finfo = null;
add(new JLabel(opt.getLabel()));
}
else
{
finfo = option.getFurtherDetails();
configureCheckbox(opt);
add(enabled);
}
/*
* construct the choice box with possible values,
* or their display names if provided
*/
val = buildComboBox(opt);
val.setSelectedItem(opt.getValue());
/*
* only show the choicebox if there is more than one option,
* or the option is mandatory
*/
if (opt.getPossibleValues().size() > 1 || opt.isRequired())
{
val.addActionListener(this);
add(val);
}
setInitialValue();
}
/**
* Configures the checkbox that controls whether or not the option is
* selected
*
* @param opt
*/
protected void configureCheckbox(OptionI opt)
{
enabled.setFont(new Font("Verdana", Font.PLAIN, 11));
enabled.addActionListener(this);
final String desc = opt.getDescription();
if (finfo != null)
{
hasLink = true;
String description = desc;
if (desc == null || desc.trim().isEmpty())
{
description = MessageManager
.getString("label.opt_and_params_further_details");
}
description = description + " ";
String text = JvSwingUtils.wrapTooltip(true, description);
enabled.setToolTipText(text);
enabled.addMouseListener(this); // for popup menu to show link
}
else
{
if (desc != null && desc.trim().length() > 0)
{
enabled.setToolTipText(JvSwingUtils.wrapTooltip(true, desc));
}
}
}
@Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() != enabled)
{
enabled.setSelected(true);
}
checkIfModified();
}
private void checkIfModified()
{
boolean notmod = (initEnabled == enabled.isSelected());
if (enabled.isSelected())
{
if (initVal != null)
{
notmod &= initVal.equals(val.getSelectedItem());
}
else
{
// compare against default service setting
notmod &= option.getValue() == null
|| option.getValue().equals(val.getSelectedItem());
}
}
else
{
notmod &= (initVal != null) ? initVal.equals(val.getSelectedItem())
: val.getSelectedItem() != initVal;
}
poparent.argSetModified(this, !notmod);
}
/**
* Answers null if the option is not selected, else a new Option holding the
* selected value
*
* @return
*/
public ArgumentI getSelectedOption()
{
if (!enabled.isSelected())
{
return null;
}
String value = getSelectedValue(option, val.getSelectedIndex());
OptionI opt = option.copy();
opt.setValue(value);
return opt;
}
@Override
public void mouseClicked(MouseEvent e)
{
if (e.isPopupTrigger()) // for Windows
{
showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
}
}
@Override
public void mouseEntered(MouseEvent e)
{
}
@Override
public void mouseExited(MouseEvent e)
{
}
@Override
public void mousePressed(MouseEvent e)
{
if (e.isPopupTrigger()) // Mac
{
showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
}
}
@Override
public void mouseReleased(MouseEvent e)
{
}
public void resetToDefault(boolean setDefaultParams)
{
enabled.setSelected(false);
if (option.isRequired()
|| (setDefaultParams && option.getValue() != null))
{
// Apply default value
selectOption(option, option.getValue());
}
}
public void setInitialValue()
{
initEnabled = enabled.isSelected();
if (option.getPossibleValues() != null
&& option.getPossibleValues().size() > 1)
{
initVal = (String) val.getSelectedItem();
}
else
{
initVal = (initEnabled) ? (String) val.getSelectedItem() : null;
}
}
/**
* toString representation for identification in the debugger only
*/
@Override
public String toString()
{
return option == null ? super.toString() : option.toString();
}
}
/**
* A class that models a panel rendering a single parameter
*/
public class ParamBox extends JPanel
implements ChangeListener, ActionListener, MouseListener
{
/*
* parameter values (or their logs) are multiplied by this
* scaling factor to ensure an integer range for the slider
*/
private int sliderScaleFactor = 1;
boolean isLogarithmicParameter;
boolean isChoiceParameter;
boolean isIntegerParameter;
boolean isStringParameter;
boolean adjusting;
/*
* drop-down list of choice options (if applicable)
*/
JComboBox choicebox;
/*
* radio buttons as an alternative to combo box
*/
ButtonGroup buttonGroup;
JPanel controlsPanel = new JPanel();
boolean descriptionIsVisible = false;
JScrollPane descPanel = new JScrollPane();
final URL finfo;
Object lastVal;
ParameterI parameter;
final OptsParametersContainerI pmdialogbox;
JPanel settingPanel = new JPanel();
JSlider slider;
JTextArea descriptionText = new JTextArea();
ValueConstrainI validator;
JTextField valueField;
private String descTooltip;
public ParamBox(final OptsParametersContainerI paramContainer,
ParameterI parm)
{
pmdialogbox = paramContainer;
finfo = parm.getFurtherDetails();
validator = parm.getValidValue();
parameter = parm;
isLogarithmicParameter = parm instanceof LogarithmicParameter;
if (validator != null)
{
ValueType type = validator.getType();
isIntegerParameter = type == ValueType.Integer;
isStringParameter = type == ValueType.String
|| type == ValueType.File;
/*
* ensure slider has an integer range corresponding to
* the min-max range of the parameter
*/
if (validator.getMin() != null && validator.getMax() != null
// && !isIntegerParameter
&& !isStringParameter)
{
double min = validator.getMin().doubleValue();
double max = validator.getMax().doubleValue();
if (isLogarithmicParameter)
{
min = Math.log(min);
max = Math.log(max);
}
sliderScaleFactor = (int) (1000000 / (max - min));
// todo scaleMin, scaleMax could also be final fields
}
}
List possibleValues = parameter.getPossibleValues();
isChoiceParameter = possibleValues != null
&& !possibleValues.isEmpty();
if (compact)
{
addCompactParameter(parm);
}
else
{
addExpandableParam(parm);
}
}
/**
* Adds a 'compact' format parameter, with any help text shown as a tooltip
*
* @param parm
*/
private void addCompactParameter(ParameterI parm)
{
setLayout(new MigLayout("", "[][grow]"));
String ttipText = null;
controlsPanel.setLayout(new BorderLayout());
if (parm.getDescription() != null
&& parm.getDescription().trim().length() > 0)
{
ttipText = (JvSwingUtils.wrapTooltip(true,
parm.getDescription() + (finfo != null ? " "
+ MessageManager.getString(
"label.opt_and_params_further_details")
: "")));
}
JvSwingUtils.addtoLayout(this, ttipText, new JLabel(parm.getName()),
controlsPanel, "");
updateControls(parm);
validate();
}
/**
* Adds an 'expanded' format parameter, with any help shown in a panel that
* may be shown or hidden
*
* @param parm
*/
private void addExpandableParam(ParameterI parm)
{
setPreferredSize(new Dimension(PARAM_WIDTH, PARAM_CLOSEDHEIGHT));
setBorder(new TitledBorder(parm.getName()));
setLayout(null);
descriptionText.setFont(new Font("Verdana", Font.PLAIN, 11));
descriptionText.setBackground(getBackground());
descriptionText.setEditable(false);
descPanel.getViewport().setView(descriptionText);
descPanel.setVisible(false);
JPanel firstrow = new JPanel();
firstrow.setLayout(null);
controlsPanel.setLayout(new BorderLayout());
controlsPanel.setBounds(new Rectangle(39, 10, PARAM_WIDTH - 70,
PARAM_CLOSEDHEIGHT - 50));
firstrow.add(controlsPanel);
firstrow.setBounds(new Rectangle(10, 20, PARAM_WIDTH - 30,
PARAM_CLOSEDHEIGHT - 30));
if (parm.getDescription() != null
&& parm.getDescription().trim().length() > 0)
{
addExpandableHelp(firstrow, parm);
}
add(firstrow);
validator = parm.getValidValue();
parameter = parm;
if (validator != null)
{
isIntegerParameter = validator.getType() == ValueType.Integer;
}
else
{
if (parameter.getPossibleValues() != null)
{
isChoiceParameter = true;
}
}
updateControls(parm);
descPanel.setBounds(new Rectangle(10, PARAM_CLOSEDHEIGHT,
PARAM_WIDTH - 20, PARAM_HEIGHT - PARAM_CLOSEDHEIGHT - 5));
add(descPanel);
validate();
}
/**
* Adds a button which can be clicked to show or hide help text
*
* @param container
* @param param
*/
protected void addExpandableHelp(JPanel container, ParameterI param)
{
JButton showDescBtn = new JButton("+");
showDescBtn.setFont(new Font("Verdana", Font.PLAIN, 8));
if (finfo != null)
{
descTooltip = JvSwingUtils.wrapTooltip(true,
MessageManager.formatMessage(
"label.opt_and_params_show_brief_desc_image_link",
new String[]
{ linkImageURL.toExternalForm() }));
showDescBtn.addMouseListener(this);
}
else
{
descTooltip = JvSwingUtils.wrapTooltip(true, MessageManager
.getString("label.opt_and_params_show_brief_desc"));
}
showDescBtn.setToolTipText(descTooltip);
showDescBtn.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
descriptionIsVisible = !descriptionIsVisible;
showDescBtn.setText(descriptionIsVisible ? "-" : "+");
showDescBtn.setToolTipText(
descriptionIsVisible ? null : descTooltip);
descPanel.setVisible(descriptionIsVisible);
descPanel.getVerticalScrollBar().setValue(0);
ParamBox.this.setPreferredSize(new Dimension(PARAM_WIDTH,
(descriptionIsVisible) ? PARAM_HEIGHT
: PARAM_CLOSEDHEIGHT));
ParamBox.this.validate();
pmdialogbox.refreshParamLayout();
}
});
descriptionText.setWrapStyleWord(true);
descriptionText.setLineWrap(true);
descriptionText.setColumns(32);
descriptionText.setText(param.getDescription());
showDescBtn.setBounds(new Rectangle(10, 10, 16, 16));
container.add(showDescBtn);
}
@Override
public void actionPerformed(ActionEvent e)
{
if (adjusting)
{
return;
}
checkIfModified();
}
/**
* Checks whether the value of this parameter has been changed and notifies
* the parent page accordingly
*/
private void checkIfModified()
{
Object newValue = updateSliderFromValueField();
boolean modified = true;
if (newValue.getClass() == lastVal.getClass())
{
modified = !newValue.equals(lastVal);
}
pmdialogbox.argSetModified(this, modified);
}
@Override
public int getBaseline(int width, int height)
{
return 0;
}
// from
// http://stackoverflow.com/questions/2743177/top-alignment-for-flowlayout
// helpful hint of using the Java 1.6 alignBaseLine property of FlowLayout
@Override
public Component.BaselineResizeBehavior getBaselineResizeBehavior()
{
return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
}
/**
* Answers an argument holding the value entered or selected in the dialog
*
* @return
*/
public ArgumentI getParameter()
{
ParameterI prm = parameter.copy();
String value = null;
if (parameter instanceof RadioChoiceParameter)
{
value = buttonGroup.getSelection().getActionCommand();
}
else if (isChoiceParameter)
{
value = getSelectedValue(this.parameter,
choicebox.getSelectedIndex());
}
else
{
value = valueField.getText();
}
prm.setValue(value);
return prm;
}
public void init()
{
// reset the widget's initial value.
lastVal = null;
}
@Override
public void mouseClicked(MouseEvent e)
{
if (e.isPopupTrigger()) // for Windows
{
showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
}
}
@Override
public void mouseEntered(MouseEvent e)
{
}
@Override
public void mouseExited(MouseEvent e)
{
}
@Override
public void mousePressed(MouseEvent e)
{
if (e.isPopupTrigger()) // for Mac
{
showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
}
}
@Override
public void mouseReleased(MouseEvent e)
{
}
@Override
public void stateChanged(ChangeEvent e)
{
if (adjusting)
{
return;
}
try
{
adjusting = true;
if (!isLogarithmicParameter)
{
/*
* set (int or float formatted) text field value
*/
valueField.setText(isIntegerParameter
? String.valueOf(slider.getValue())
: formatDouble(
slider.getValue() / (float) sliderScaleFactor));
}
else
{
double value = Math.pow(Math.E,
slider.getValue() / (double) sliderScaleFactor);
valueField.setText(formatDouble(value));
}
checkIfModified();
} finally
{
adjusting = false;
}
}
/**
* Answers the value formatted as a string to 3 decimal places - in
* scientific notation if the value is less than 0.001
*
* @param value
* @return
*/
String formatDouble(double value)
{
String format = value < 0.001 ? "%3.1E" : "%3.3f";
return String.format(format, value);
}
/**
* Formats a number as integer or float (3dp) or scientific notation (1dp)
*
* @param n
* @return
*/
String formatNumber(Number n)
{
return n instanceof Integer ? String.valueOf(n.intValue())
: formatDouble(n.doubleValue());
}
void updateControls(ParameterI parm)
{
adjusting = true;
boolean init = (choicebox == null && valueField == null
&& buttonGroup == null);
if (init)
{
if (parm instanceof RadioChoiceParameter)
{
buttonGroup = addRadioButtons(parameter, controlsPanel);
}
else if (isChoiceParameter)
{
choicebox = buildComboBox(parm);
choicebox.addActionListener(this);
controlsPanel.add(choicebox, BorderLayout.CENTER);
}
else
{
slider = new JSlider();
slider.addChangeListener(this);
int cols = parm instanceof StringParameter ? 20 : 0;
valueField = new JTextField(cols);
valueField.addActionListener(this);
valueField.addKeyListener(new KeyAdapter()
{
@Override
public void keyReleased(KeyEvent e)
{
int keyCode = e.getKeyCode();
if (e.isActionKey() && keyCode != KeyEvent.VK_LEFT
&& keyCode != KeyEvent.VK_RIGHT)
{
if (valueField.getText().trim().length() > 0)
{
actionPerformed(null);
}
}
}
});
valueField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e)
{
actionPerformed(null);
}
});
valueField.setPreferredSize(new Dimension(65, 25));
if (parm instanceof FileParameter)
{
valueField.setToolTipText(MessageManager
.getString("label.double_click_to_browse"));
valueField.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 2)
{
String dir = Cache.getProperty("LAST_DIRECTORY");
JalviewFileChooser chooser = new JalviewFileChooser(dir);
chooser.setFileView(new JalviewFileView());
chooser.setDialogTitle(
MessageManager.getString("action.select_ddbb"));
int val = chooser.showOpenDialog(ParamBox.this);
if (val == JalviewFileChooser.APPROVE_OPTION)
{
File choice = chooser.getSelectedFile();
String path = choice.getPath();
valueField.setText(path);
Cache.setProperty("LAST_DIRECTORY", choice.getParent());
FileLoader.updateRecentlyOpened(path,
DataSourceType.FILE);
}
}
}
});
}
controlsPanel.add(slider, BorderLayout.WEST);
controlsPanel.add(valueField, BorderLayout.EAST);
}
}
String value = parm.getValue();
if (value != null)
{
if (isChoiceParameter)
{
if (!(parm instanceof RadioChoiceParameter))
{
choicebox.setSelectedItem(value);
}
}
else
{
valueField.setText(value);
}
}
lastVal = updateSliderFromValueField();
adjusting = false;
}
/**
* Adds a panel to comp, containing a label and radio buttons for the choice
* of values of the given option. Returns a ButtonGroup whose members are
* the added radio buttons.
*
* @param option
* @param comp
*
* @return
*/
protected ButtonGroup addRadioButtons(OptionI option, Container comp)
{
ButtonGroup bg = new ButtonGroup();
JPanel radioPanel = new JPanel();
radioPanel.add(new JLabel(option.getDescription()));
String value = option.getValue();
for (String opt : option.getPossibleValues())
{
JRadioButton btn = new JRadioButton(opt);
btn.setActionCommand(opt);
boolean selected = opt.equals(value);
btn.setSelected(selected);
btn.addActionListener(this);
bg.add(btn);
radioPanel.add(btn);
}
comp.add(radioPanel);
return bg;
}
/**
* Action depends on the type of the input parameter:
*
* if a text input, returns the trimmed value
* if a choice list or radio button, returns the selected value
* if a value slider and input field, sets the value of the slider from
* the value in the text field, limiting it to any defined min-max
* range.
*
* Answers the (possibly modified) input value, as a String, Integer, Float
* or Double.
*
* @return
*/
Object updateSliderFromValueField()
{
if (validator == null || isStringParameter)
{
if (isChoiceParameter)
{
if (parameter instanceof RadioChoiceParameter)
{
return buttonGroup.getSelection().getActionCommand();
}
else
{
return getSelectedValue(this.parameter,
choicebox.getSelectedIndex());
}
}
slider.setVisible(false);
return valueField.getText().trim();
}
if (validator.getMin() == null || validator.getMax() == null)
{
slider.setVisible(false);
}
valueField.setText(valueField.getText().trim());
/*
* ensure not outside min-max range
* TODO: provide some visual indicator if limit reached
*/
try
{
valueField.setBackground(Color.WHITE);
double d = Double.parseDouble(valueField.getText());
if (validator.getMin() != null
&& validator.getMin().doubleValue() > d)
{
valueField.setText(formatNumber(validator.getMin()));
}
if (validator.getMax() != null
&& validator.getMax().doubleValue() < d)
{
valueField.setText(formatNumber(validator.getMax()));
}
} catch (NumberFormatException e)
{
valueField.setBackground(Color.yellow);
return Float.NaN;
}
if (isIntegerParameter)
{
int iVal = 0;
try
{
iVal = Integer.valueOf(valueField.getText());
} catch (Exception e)
{
valueField.setBackground(Color.yellow);
return Integer.valueOf(0);
}
if (validator.getMin() != null && validator.getMax() != null)
{
slider.getModel().setRangeProperties(iVal, 1,
validator.getMin().intValue(),
validator.getMax().intValue() + 1, true);
}
else
{
slider.setVisible(false);
}
return Integer.valueOf(iVal);
}
if (isLogarithmicParameter)
{
double dVal = 0d;
try
{
double eValue = Double.valueOf(valueField.getText());
dVal = Math.log(eValue);
} catch (Exception e)
{
// shouldn't be possible here
valueField.setBackground(Color.yellow);
return Double.NaN;
}
if (validator.getMin() != null && validator.getMax() != null)
{
double scaleMin = Math.log(validator.getMin().doubleValue())
* sliderScaleFactor;
double scaleMax = Math.log(validator.getMax().doubleValue())
* sliderScaleFactor;
slider.getModel().setRangeProperties(
(int) (sliderScaleFactor * dVal), 1,
(int) scaleMin, 1 + (int) scaleMax, true);
}
else
{
slider.setVisible(false);
}
return Double.valueOf(dVal);
}
float fVal = 0f;
try
{
fVal = Float.valueOf(valueField.getText());
} catch (Exception e)
{
return Float.valueOf(0f); // shouldn't happen
}
if (validator.getMin() != null && validator.getMax() != null)
{
float scaleMin = validator.getMin().floatValue()
* sliderScaleFactor;
float scaleMax = validator.getMax().floatValue()
* sliderScaleFactor;
slider.getModel().setRangeProperties(
(int) (fVal * sliderScaleFactor), 1, (int) scaleMin,
1 + (int) scaleMax, true);
}
else
{
slider.setVisible(false);
}
return Float.valueOf(fVal);
}
}
/**
* Constructor with the option to show 'compact' format (parameter description
* as tooltip) or 'expanded' format (parameter description in a textbox which
* may be opened or closed). Use compact for simple description text, expanded
* for more wordy or formatted text.
*
* @param paramContainer
*/
public OptsAndParamsPage(OptsParametersContainerI paramContainer,
boolean compact)
{
poparent = paramContainer;
this.compact = compact;
}
public static void showUrlPopUp(JComponent invoker, final String finfo,
int x, int y)
{
JPopupMenu mnu = new JPopupMenu();
JMenuItem mitem = new JMenuItem(
MessageManager.formatMessage("label.view_params", new String[]
{ finfo }));
mitem.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
Desktop.showUrl(finfo);
}
});
mnu.add(mitem);
mnu.show(invoker, x, y);
}
public Map getOptSet()
{
return optSet;
}
public void setOptSet(Map optSet)
{
this.optSet = optSet;
}
public Map getParamSet()
{
return paramSet;
}
public void setParamSet(Map paramSet)
{
this.paramSet = paramSet;
}
OptionBox addOption(OptionI opt)
{
OptionBox cb = optSet.get(opt.getName());
if (cb == null)
{
cb = new OptionBox(opt);
optSet.put(opt.getName(), cb);
// jobOptions.add(cb, FlowLayout.LEFT);
}
return cb;
}
ParamBox addParameter(ParameterI arg)
{
ParamBox pb = paramSet.get(arg.getName());
if (pb == null)
{
pb = new ParamBox(poparent, arg);
paramSet.put(arg.getName(), pb);
// paramList.add(pb);
}
pb.init();
// take the defaults from the parameter
pb.updateControls(arg);
return pb;
}
void selectOption(OptionI option, String string)
{
OptionBox cb = optSet.get(option.getName());
if (cb == null)
{
cb = addOption(option);
}
cb.enabled.setSelected(string != null); // initial state for an option.
if (string != null)
{
if (option.getPossibleValues().contains(string))
{
cb.val.setSelectedItem(string);
}
else
{
throw new Error(MessageManager.formatMessage(
"error.invalid_value_for_option", new String[]
{ string, option.getName() }));
}
}
if (option.isRequired() && !cb.enabled.isSelected())
{
// TODO: indicate paramset is not valid.. option needs to be selected!
}
cb.setInitialValue();
}
void setParameter(ParameterI arg)
{
ParamBox pb = paramSet.get(arg.getName());
if (pb == null)
{
addParameter(arg);
}
else
{
pb.updateControls(arg);
}
}
/**
* Answers a list of arguments representing all the options and arguments
* selected on the dialog, holding their chosen or input values. Optional
* parameters which were not selected are not included.
*
* @return
*/
public List getCurrentSettings()
{
List argSet = new ArrayList<>();
for (OptionBox opts : getOptSet().values())
{
ArgumentI opt = opts.getSelectedOption();
if (opt != null)
{
argSet.add(opt);
}
}
for (ParamBox parambox : getParamSet().values())
{
ArgumentI parm = parambox.getParameter();
if (parm != null)
{
argSet.add(parm);
}
}
return argSet;
}
/**
* A helper method that constructs and returns a CombBox for choice of the
* possible option values. If display names are provided, then these are added
* as options, otherwise the actual values are added.
*
* @param opt
* @return
*/
protected static JComboBox buildComboBox(OptionI opt)
{
JComboBox cb = null;
List displayNames = opt.getDisplayNames();
if (displayNames != null)
{
List displayNamesObjects = new ArrayList<>();
displayNamesObjects.addAll(displayNames);
cb = JvSwingUtils.buildComboWithTooltips(displayNamesObjects,
opt.getPossibleValues());
}
else
{
cb = new JComboBox<>();
for (String v : opt.getPossibleValues())
{
cb.addItem(v);
}
}
return cb;
}
/**
* Answers the value corresponding to the selected item in the choice combo
* box. Note that this returns the underlying value even if a different
* display name is used in the combo box.
*
* @return
*/
protected static String getSelectedValue(OptionI opt, int sel)
{
List possibleValues = opt.getPossibleValues();
String value = null;
if (possibleValues != null && possibleValues.size() == 1)
{
// Hack to make sure the default value for an enabled option with only
// one value is actually returned even if this.val is not displayed
value = possibleValues.get(0);
}
else if (sel >= 0 && sel < possibleValues.size())
{
value = possibleValues.get(sel);
}
return value;
}
}