package beast.app.draw;
import java.awt.Dimension;
import java.util.List;
import javax.swing.Box;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.border.EtchedBorder;
import beast.app.beauti.BeautiDoc;
import beast.app.beauti.BeautiSubTemplate;
import beast.core.BEASTInterface;
import beast.core.Input;
import beast.util.AddOnManager;
public class BEASTObjectInputEditor extends InputEditor.Base {
private static final long serialVersionUID = 1L;
JComboBox<Object> m_selectBEASTObjectBox;
SmallButton m_editBEASTObjectButton;
BEASTObjectInputEditor _this;
public BEASTObjectInputEditor(BeautiDoc doc) {
super(doc);
_this = this;
}
@Override
public Class<?> type() {
return BEASTInterface.class;
}
/**
* construct an editor consisting of
* o a label
* o a combo box for selecting another plug-in
* o a button for editing the plug-in
* o validation label -- optional, if input is not valid
*/
@Override
public void init(Input<?> input, BEASTInterface beastObject, int itemNr, ExpandOption isExpandOption, boolean addButtons) {
//box.setAlignmentY(LEFT_ALIGNMENT);
m_bAddButtons = addButtons;
m_input = input;
m_beastObject = beastObject;
this.itemNr = itemNr;
if (isExpandOption == ExpandOption.FALSE) {
simpleInit(input, beastObject);
} else {
expandedInit(input, beastObject);
}
} // init
/**
* add combobox with available beastObjects
* a button to edit that beastObject +
* a validation icon
* *
*/
void simpleInit(Input<?> input, BEASTInterface beastObject) {
addInputLabel();
addComboBox(this, input, beastObject);
if (m_bAddButtons) {
if (BEASTObjectPanel.countInputs((BEASTInterface) m_input.get(), doc) > 0) {
m_editBEASTObjectButton = new SmallButton("e", true);
if (input.get() == null) {
m_editBEASTObjectButton.setEnabled(false);
}
m_editBEASTObjectButton.setToolTipText("Edit " + m_inputLabel.getText());
m_editBEASTObjectButton.addActionListener(e -> {
BEASTObjectDialog dlg = new BEASTObjectDialog((BEASTInterface) m_input.get(), m_input.getType(), doc);
if (dlg.showDialog()) {
try {
dlg.accept((BEASTInterface) m_input.get(), doc);
} catch (Exception ex) {
ex.printStackTrace();
}
}
refresh();
validateInput();
refreshPanel();
});
add(m_editBEASTObjectButton);
}
}
addValidationLabel();
} // init
void refresh() {
if (m_selectBEASTObjectBox != null) {
String oldID = (String) m_selectBEASTObjectBox.getSelectedItem();
String id = ((BEASTInterface) m_input.get()).getID();
if (!id.equals(oldID)) {
m_selectBEASTObjectBox.addItem(id);
m_selectBEASTObjectBox.setSelectedItem(id);
m_selectBEASTObjectBox.removeItem(oldID);
}
}
super.refreshPanel();
// Component c = this;
// while (((Component) c).getParent() != null) {
// c = ((Component) c).getParent();
// if (c instanceof ListSelectionListener) {
// ((ListSelectionListener) c).valueChanged(null);
// }
// }
}
void initSelectPluginBox() {
List<String> availableBEASTObjects = doc.getInputEditorFactory().getAvailablePlugins(m_input, m_beastObject, null, doc);
if (availableBEASTObjects.size() > 0) {
availableBEASTObjects.add(NO_VALUE);
for (int i = 0; i < availableBEASTObjects.size(); i++) {
String beastObjectName = availableBEASTObjects.get(i);
if (beastObjectName.startsWith("new ")) {
beastObjectName = beastObjectName.substring(beastObjectName.lastIndexOf('.'));
availableBEASTObjects.set(i, beastObjectName);
}
}
m_selectBEASTObjectBox.removeAllItems();
for (String str : availableBEASTObjects.toArray(new String[0])) {
m_selectBEASTObjectBox.addItem(str);
}
m_selectBEASTObjectBox.setSelectedItem(m_beastObject.getID());
}
}
Box m_expansionBox = null;
void expandedInit(Input<?> input, BEASTInterface beastObject) {
addInputLabel();
Box box = Box.createVerticalBox();
// add horizontal box with combobox of BEASTObjects to select from
Box combobox = Box.createHorizontalBox();
addComboBox(combobox, input, beastObject);
box.add(combobox);
doc.getInputEditorFactory().addInputs(box, (BEASTInterface) input.get(), this, this, doc);
box.setBorder(new EtchedBorder());
//box.setBorder(BorderFactory.createLineBorder(Color.BLUE));
add(box);
m_expansionBox = box;
} // expandedInit
/**
* add combobox with BEASTObjects to choose from
* On choosing a new value, create beastObject (if is not already an object)
* Furthermore, if expanded, update expanded inputs
*/
protected void addComboBox(JComponent box, Input<?> input, BEASTInterface beastObject0) {
if (itemNr >= 0) {
box.add(new JLabel(beastObject0.getID()));
box.add(Box.createGlue());
return;
}
List<BeautiSubTemplate> availableTemplates = doc.getInputEditorFactory().getAvailableTemplates(m_input, m_beastObject, null, doc);
if (availableTemplates.size() > 0) {
// if (m_input.getRule() != Validate.REQUIRED || beastObject == null) {
// availableBEASTObjects.add(NO_VALUE);
// }
// for (int i = 0; i < availableBEASTObjects.size(); i++) {
// String beastObjectName = availableBEASTObjects.get(i);
// if (beastObjectName.startsWith("new ")) {
// beastObjectName = beastObjectName.substring(beastObjectName.lastIndexOf('.'));
// availableBEASTObjects.set(i, beastObjectName);
// }
//
// }
m_selectBEASTObjectBox = new JComboBox<>(availableTemplates.toArray());
m_selectBEASTObjectBox.setName(input.getName());
Object o = input.get();
if (itemNr >= 0) {
o = ((List<?>)o).get(itemNr);
}
String id2;
if (o == null) {
id2 = beastObject0.getID();
} else {
id2 = ((BEASTInterface) o).getID();
}
if (id2.indexOf('.')>=0) {
id2 = id2.substring(0, id2.indexOf('.'));
}
for (BeautiSubTemplate template : availableTemplates) {
if (template.matchesName(id2)) {
m_selectBEASTObjectBox.setSelectedItem(template);
}
}
m_selectBEASTObjectBox.addActionListener(e -> {
// SwingUtilities.invokeLater(new Runnable() {
//
// @Override
// public void run() {
// get a handle of the selected beastObject
BeautiSubTemplate selected = (BeautiSubTemplate) m_selectBEASTObjectBox.getSelectedItem();
BEASTInterface beastObject = (BEASTInterface) m_input.get();
String id = beastObject.getID();
String partition = id.substring(id.indexOf('.') + 1);
if (partition.indexOf(':') >= 0) {
partition = id.substring(id.indexOf(':') + 1);
}
//String newID = selected.getMainID().replaceAll("\\$\\(n\\)", partition);
if (selected.equals(NO_VALUE)) {
beastObject = null;
// } else if (PluginPanel.g_plugins.containsKey(newID)) {
// beastObject = PluginPanel.g_plugins.get(newID);
} else {
try {
beastObject = selected.createSubNet(doc.getContextFor(beastObject), m_beastObject, m_input, true);
//PluginPanel.addPluginToMap(beastObject);
// tricky: try to connect up new inputs with old inputs of existing name
// beastObject oldPlugin = (beastObject) m_input.get();
// for (Input<?> oldInput: oldPlugin.listInputs()) {
// String name = oldInput.getName();
// try {
// Input<?> newInput = beastObject.getInput(name);
// if (newInput.get() instanceof List) {
// List<?> values = (List<?>) oldInput.get();
// for (Object value: values) {
// newInput.setValue(value, beastObject);
// }
// } else {
// newInput.setValue(oldInput.get(), beastObject);
// }
// } catch (Exception ex) {
// // ignore
// }
// }
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Could not select beastObject: " +
ex.getClass().getName() + " " +
ex.getMessage()
);
}
}
try {
if (beastObject == null) {
m_selectBEASTObjectBox.setSelectedItem(NO_VALUE);
// is this input expanded?
if (m_expansionBox != null) {
// remove items from Expansion Box, if any
for (int i = 1; i < m_expansionBox.getComponentCount(); i++) {
m_expansionBox.remove(i);
}
} else { // not expanded
if (m_bAddButtons && m_editBEASTObjectButton != null) {
m_editBEASTObjectButton.setEnabled(false);
}
}
} else {
if (!m_input.canSetValue(beastObject, m_beastObject)) {
throw new IllegalArgumentException("Cannot set input to this value");
}
// // get handle on ID of the beastObject, and add to combobox if necessary
// String id = beastObject.getID();
// // TODO RRB: have to remove ID first, then add it
// // The addition is necessary to make the items in the expansionBox scale and show up
// // Is there another way?
// m_selectPluginBox.removeItem(id);
// m_selectPluginBox.addItem(id);
// m_selectPluginBox.setSelectedItem(id);
id = beastObject.getID();
id = id.substring(0, id.indexOf('.'));
for (int i = 0; i < m_selectBEASTObjectBox.getItemCount(); i++) {
BeautiSubTemplate template = (BeautiSubTemplate) m_selectBEASTObjectBox.getItemAt(i);
if (template.getMainID().replaceAll(".\\$\\(n\\)", "").equals(id) ||
template.getMainID().replaceAll(".s:\\$\\(n\\)", "").equals(id) ||
template.getMainID().replaceAll(".c:\\$\\(n\\)", "").equals(id) ||
template.getMainID().replaceAll(".t:\\$\\(n\\)", "").equals(id)) {
m_selectBEASTObjectBox.setSelectedItem(template);
}
}
}
setValue(beastObject);
//m_input.setValue(beastObject, m_beastObject);
if (m_expansionBox != null) {
// remove items from Expansion Box
for (int i = 1; i < m_expansionBox.getComponentCount(); ) {
m_expansionBox.remove(i);
}
// add new items to Expansion Box
if (beastObject != null) {
doc.getInputEditorFactory().addInputs(m_expansionBox, beastObject, _this, _this, doc);
}
} else {
// it is not expanded, enable the edit button
if (m_bAddButtons && m_editBEASTObjectButton != null) {
m_editBEASTObjectButton.setEnabled(true);
}
validateInput();
}
sync();
refreshPanel();
} catch (Exception ex) {
id = ((BEASTInterface) m_input.get()).getID();
m_selectBEASTObjectBox.setSelectedItem(id);
ex.printStackTrace();
JOptionPane.showMessageDialog(null, "Could not change beastObject: " +
ex.getClass().getName() + " " +
ex.getMessage()
);
}
});
m_selectBEASTObjectBox.setToolTipText(input.getHTMLTipText());
int fontsize = m_selectBEASTObjectBox.getFont().getSize();
m_selectBEASTObjectBox.setMaximumSize(new Dimension(1024, 200 * fontsize / 13));
box.add(m_selectBEASTObjectBox);
}
}
// protected void addComboBox2(Box box, Input <?> input, BEASTObject beastObject) {
// List<String> availableBEASTObjects = PluginPanel.getAvailablePlugins(m_input, m_beastObject, null);
// if (availableBEASTObjects.size() > 0) {
// if (m_input.getRule() != Validate.REQUIRED || beastObject == null) {
// availableBEASTObjects.add(NO_VALUE);
// }
// for (int i = 0; i < availableBEASTObjects.size(); i++) {
// String beastObjectName = availableBEASTObjects.get(i);
// if (beastObjectName.startsWith("new ")) {
// beastObjectName = beastObjectName.substring(beastObjectName.lastIndexOf('.'));
// availableBEASTObjects.set(i, beastObjectName);
// }
//
// }
// m_selectPluginBox = new JComboBox(availableBEASTObjects.toArray(new String[0]));
// String selectString = NO_VALUE;
// if (input.get() != null) {
// selectString = ((BEASTObject) input.get()).getID();
// }
// m_selectPluginBox.setSelectedItem(selectString);
//
// m_selectPluginBox.addActionListener(new ActionListener() {
// // implements ActionListener
// public void actionPerformed(ActionEvent e) {
//
// // get a handle of the selected beastObject
// String selected = (String) m_selectPluginBox.getSelectedItem();
// BEASTObject beastObject = (BEASTObject) m_input.get();
// if (selected.equals(NO_VALUE)) {
// beastObject = null;
// } else if (!selected.startsWith(".")) {
// beastObject = PluginPanel.g_plugins.get(selected);
// } else {
// List<String> availableBEASTObjects = PluginPanel.getAvailablePlugins(m_input, m_beastObject, null);
// int i = 0;
// while (!availableBEASTObjects.get(i).matches(".*\\"+selected+"$")) {
// i++;
// }
// selected = availableBEASTObjects.get(i);
// /* create new beastObject */
// try {
// beastObject = (BEASTObject) Class.forName(selected.substring(4)).newInstance();
// PluginPanel.addPluginToMap(beastObject);
// // tricky: try to connect up new inputs with old inputs of existing name
// BEASTObject oldPlugin = (BEASTObject) m_input.get();
// for (Input<?> oldInput: oldPlugin.listInputs()) {
// String name = oldInput.getName();
// try {
// Input<?> newInput = beastObject.getInput(name);
// if (newInput.get() instanceof List) {
// List<?> values = (List<?>) oldInput.get();
// for (Object value: values) {
// newInput.setValue(value, beastObject);
// }
// } else {
// newInput.setValue(oldInput.get(), beastObject);
// }
// } catch (Exception ex) {
// // ignore
// }
// }
//
// } catch (Exception ex) {
// JOptionPane.showMessageDialog(null, "Could not select beastObject: " +
// ex.getClass().getName() + " " +
// ex.getMessage()
// );
// }
// }
//
//
// try {
// if (beastObject == null) {
// m_selectPluginBox.setSelectedItem(NO_VALUE);
// // is this input expanded?
// if (m_expansionBox != null) {
// // remove items from Expansion Box, if any
// for (int i = 1; i < m_expansionBox.getComponentCount(); i++) {
// m_expansionBox.remove(i);
// }
// } else { // not expanded
// if (m_bAddButtons) {
// m_editPluginButton.setEnabled(false);
// }
// }
// } else {
// if (!m_input.canSetValue(beastObject, m_beastObject)) {
// throw new Exception("Cannot set input to this value");
// }
// // get handle on ID of the beastObject, and add to combobox if necessary
// String id = beastObject.getID();
// // TODO RRB: have to remove ID first, then add it
// // The addition is necessary to make the items in the expansionBox scale and show up
// // Is there another way?
// m_selectPluginBox.removeItem(id);
// m_selectPluginBox.addItem(id);
// m_selectPluginBox.setSelectedItem(id);
// }
//
// m_input.setValue(beastObject, m_beastObject);
//
// if (m_expansionBox != null) {
// // remove items from Expansion Box
// for (int i = 1; i < m_expansionBox.getComponentCount(); ) {
// m_expansionBox.remove(i);
// }
// // add new items to Expansion Box
// if (beastObject != null) {
// PluginPanel.addInputs(m_expansionBox, beastObject, _this, _this);
// }
// } else {
// // it is not expanded, enable the edit button
// if (m_bAddButtons) {
// m_editPluginButton.setEnabled(true);
// }
// checkValidation();
// }
//
// } catch (Exception ex) {
// String id = ((BEASTObject)m_input.get()).getID();
// m_selectPluginBox.setSelectedItem(id);
// //ex.printStackTrace();
// JOptionPane.showMessageDialog(null, "Could not change beastObject: " +
// ex.getClass().getName() + " " +
// ex.getMessage()
// );
// }
// }
// });
// m_selectPluginBox.setToolTipText(input.getTipText());
// m_selectPluginBox.setMaximumSize(new Dimension(1024, 20));
// box.add(m_selectPluginBox);
// }
// }
String[] getAvailablePlugins() {
List<String> beastObjectNames = AddOnManager.find(m_input.getType(), "beast");
return beastObjectNames.toArray(new String[0]);
} // getAvailablePlugins
} // class PluginInputEditor