package beast.app.draw;
import java.awt.Color;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import beast.app.beauti.BeautiDoc;
import beast.app.beauti.BeautiPanel;
import beast.app.beauti.PartitionContext;
import beast.app.util.Utils;
import beast.core.BEASTInterface;
import beast.core.Distribution;
import beast.core.Input;
import beast.core.Operator;
import beast.core.parameter.Parameter;
import beast.core.util.Log;
import beast.evolution.branchratemodel.BranchRateModel;
import beast.math.distributions.ParametricDistribution;
public class ParameterInputEditor extends BEASTObjectInputEditor {
boolean isParametricDistributionParameter = false;
//public ParameterInputEditor() {}
public ParameterInputEditor(BeautiDoc doc) {
super(doc);
}
private static final long serialVersionUID = 1L;
public JCheckBox m_isEstimatedBox;
@Override
public Class<?> type() {
return Parameter.Base.class;
}
@Override
public void init(Input<?> input, BEASTInterface beastObject, int itemNr, ExpandOption isExpandOption, boolean addButtons) {
super.init(input, beastObject, itemNr, isExpandOption, addButtons);
m_beastObject = beastObject;
}
@Override
protected void initEntry() {
if (m_input.get() != null) {
if (itemNr < 0) {
Parameter.Base<?> parameter = (Parameter.Base<?>) m_input.get();
String s = "";
for (Object d : parameter.valuesInput.get()) {
s += d + " ";
}
m_entry.setText(s);
} else {
Parameter.Base<?> parameter = (Parameter.Base<?>) ((List<?>)m_input.get()).get(itemNr);
String s = "";
for (Object d : parameter.valuesInput.get()) {
s += d + " ";
}
m_entry.setText(s);
}
}
}
@Override
protected void processEntry() {
try {
String valueString = m_entry.getText();
Parameter.Base<?> parameter = (Parameter.Base<?>) m_input.get();
String oldValue = "";
for (Object d : parameter.valuesInput.get()) {
oldValue += d + " ";
}
int oldDim = parameter.getDimension();
parameter.valuesInput.setValue(valueString, parameter);
parameter.initAndValidate();
int newDim = parameter.getDimension();
if (oldDim != newDim) {
parameter.setDimension(oldDim);
parameter.valuesInput.setValue(oldValue, parameter);
parameter.initAndValidate();
throw new IllegalArgumentException("Entry caused change in dimension");
}
validateInput();
} catch (Exception ex) {
m_validateLabel.setVisible(true);
m_validateLabel.setToolTipText("<html><p>Parsing error: " + ex.getMessage() + ". Value was left at " + m_input.get() + ".</p></html>");
m_validateLabel.m_circleColor = Color.orange;
repaint();
}
}
@Override
protected void addComboBox(JComponent box, Input<?> input, BEASTInterface beastObject) {
Box paramBox = Box.createHorizontalBox();
Parameter.Base<?> parameter = null;
if (itemNr >= 0) {
parameter = (Parameter.Base<?>) ((List<?>) input.get()).get(itemNr);
} else {
parameter = (Parameter.Base<?>) input.get();
}
if (parameter == null) {
super.addComboBox(box, input, beastObject);
} else {
setUpEntry();
paramBox.add(m_entry);
if (doc.allowLinking) {
boolean isLinked = doc.isLinked(m_input);
if (isLinked || doc.suggestedLinks((BEASTInterface) m_input.get()).size() > 0) {
JButton linkbutton = new JButton(Utils.getIcon(BeautiPanel.ICONPATH +
(isLinked ? "link.png" : "unlink.png")));
linkbutton.setBorder(BorderFactory.createEmptyBorder());
linkbutton.setToolTipText("link/unlink this parameter with another compatible parameter");
linkbutton.addActionListener(e -> {
if (doc.isLinked(m_input)) {
// unlink
try {
BEASTInterface candidate = doc.getUnlinkCandidate(m_input, m_beastObject);
m_input.setValue(candidate, m_beastObject);
doc.deLink(m_input);
} catch (RuntimeException e2) {
e2.printStackTrace();
JOptionPane.showMessageDialog(this, "Could not unlink: " + e2.getMessage());
}
} else {
// create a link
List<BEASTInterface> candidates = doc.suggestedLinks((BEASTInterface) m_input.get());
JComboBox<BEASTInterface> jcb = new JComboBox<>(candidates.toArray(new BEASTInterface[]{}));
JOptionPane.showMessageDialog( null, jcb, "select parameter to link with", JOptionPane.QUESTION_MESSAGE);
BEASTInterface candidate = (BEASTInterface) jcb.getSelectedItem();
if (candidate != null) {
try {
m_input.setValue(candidate, m_beastObject);
doc.addLink(m_input);
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
refreshPanel();
});
paramBox.add(linkbutton);
}
}
paramBox.add(Box.createHorizontalGlue());
m_isEstimatedBox = new JCheckBox(doc.beautiConfig.getInputLabel(parameter, parameter.isEstimatedInput.getName()));
m_isEstimatedBox.setName(input.getName() + ".isEstimated");
if (input.get() != null) {
m_isEstimatedBox.setSelected(parameter.isEstimatedInput.get());
}
m_isEstimatedBox.setToolTipText(parameter.isEstimatedInput.getHTMLTipText());
boolean isClockRate = false;
for (Object output : parameter.getOutputs()) {
if (output instanceof BranchRateModel.Base) {
isClockRate |= ((BranchRateModel.Base) output).meanRateInput.get() == parameter;
}
}
m_isEstimatedBox.setEnabled(!isClockRate || !getDoc().autoSetClockRate);
m_isEstimatedBox.addActionListener(e -> {
try {
Parameter.Base<?> parameter2 = (Parameter.Base<?>) m_input.get();
parameter2.isEstimatedInput.setValue(m_isEstimatedBox.isSelected(), parameter2);
if (isParametricDistributionParameter) {
String id = parameter2.getID();
if (id.startsWith("RealParameter")) {
ParametricDistribution parent = null;
for (Object beastObject2 : parameter2.getOutputs()) {
if (beastObject2 instanceof ParametricDistribution) {
parent = (ParametricDistribution) beastObject2;
break;
}
}
Distribution grandparent = null;
for (Object beastObject2 : parent.getOutputs()) {
if (beastObject2 instanceof Distribution) {
grandparent = (Distribution) beastObject2;
break;
}
}
id = "parameter.hyper" + parent.getClass().getSimpleName() + "-" +
m_input.getName() + "-" + grandparent.getID();
doc.pluginmap.remove(parameter2.getID());
parameter2.setID(id);
doc.addPlugin(parameter2);
}
PartitionContext context = new PartitionContext(id.substring("parameter.".length()));
Log.warning.println(context + " " + id);
doc.beautiConfig.hyperPriorTemplate.createSubNet(context, true);
}
refreshPanel();
} catch (Exception ex) {
Log.err.println("ParameterInputEditor " + ex.getMessage());
}
});
paramBox.add(m_isEstimatedBox);
// only show the estimate flag if there is an operator that works on this parameter
m_isEstimatedBox.setVisible(doc.isExpertMode());
m_isEstimatedBox.setToolTipText("Estimate value of this parameter in the MCMC chain");
//m_editPluginButton.setVisible(false);
//m_bAddButtons = false;
if (itemNr < 0) {
for (Object beastObject2 : ((BEASTInterface) m_input.get()).getOutputs()) {
if (beastObject2 instanceof ParametricDistribution) {
m_isEstimatedBox.setVisible(true);
isParametricDistributionParameter = true;
break;
}
}
for (Object beastObject2 : ((BEASTInterface) m_input.get()).getOutputs()) {
if (beastObject2 instanceof Operator) {
m_isEstimatedBox.setVisible(true);
//m_editPluginButton.setVisible(true);
break;
}
}
} else {
for (Object beastObject2 : ((BEASTInterface) ((List<?>)m_input.get()).get(itemNr)).getOutputs()) {
if (beastObject2 instanceof Operator) {
m_isEstimatedBox.setVisible(true);
//m_editPluginButton.setVisible(true);
break;
}
}
}
box.add(paramBox);
}
}
@Override
protected void addValidationLabel() {
super.addValidationLabel();
// make edit button invisible (if it exists) when this parameter is not estimateable
if (m_editBEASTObjectButton != null)
m_editBEASTObjectButton.setVisible(m_isEstimatedBox.isVisible());
}
@Override
void refresh() {
Parameter.Base<?> parameter = (Parameter.Base<?>) m_input.get();
String s = "";
for (Object d : parameter.valuesInput.get()) {
s += d + " ";
}
m_entry.setText(s);
m_isEstimatedBox.setSelected(parameter.isEstimatedInput.get());
repaint();
}
}