package beast.app.beauti;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import beast.evolution.alignment.Taxon;
import beast.evolution.alignment.TaxonSet;
public class TaxonSetDialog extends JDialog {
private static final long serialVersionUID = 1L;
public boolean isOK = false;
TaxonSet taxonSet;
String id;
List<Taxon> _candidates;
JTextField idEntry;
JTextField filterEntry;
JList<Taxon> listOfTaxonCandidates;
DefaultListModel<Taxon> listModel1;
JList<Taxon> listOfTaxonSet;
DefaultListModel<Taxon> listModel2;
Box box;
BeautiDoc doc;
public TaxonSetDialog(TaxonSet taxonSet, Set<Taxon> candidates, BeautiDoc doc) {
// initialize state
this.taxonSet = taxonSet;
this.doc = doc;
id = taxonSet.getID();
// create components
box = Box.createVerticalBox();
box.add(createIDBox());
box.add(createFilterBox());
box.add(createTaxonSelector());
box.add(Box.createVerticalGlue());
//box.add(createCancelOKButtons());
// initialise lists
List<Taxon> taxonset = taxonSet.taxonsetInput.get();
Comparator<Taxon> comparator = (o1, o2) -> o1.getID().compareTo(o2.getID());
Collections.sort(taxonset, comparator);
_candidates = new ArrayList<>();
_candidates.addAll(candidates);
Collections.sort(_candidates, comparator);
for (Taxon taxon : taxonset) {
listModel2.addElement(taxon);
}
for (Taxon taxon : _candidates) {
listModel1.addElement(taxon);
}
for (int i = 0; i < listModel2.size(); i++) {
listModel1.removeElement(listModel2.get(i));
}
add(box);
int size = UIManager.getFont("Label.font").getSize();
setSize(400 * size / 13, 600 * size / 13);
setModal(true);
} // c'tor
public boolean showDialog() {
JOptionPane optionPane = new JOptionPane(box,
JOptionPane.QUESTION_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
null,
null,
null);
optionPane.setBorder(new EmptyBorder(12, 12, 12, 12));
Frame frame = (doc != null ? doc.getFrame(): Frame.getFrames()[0]);
final JDialog dialog = optionPane.createDialog(frame, "Taxon set editor");
dialog.pack();
dialog.setVisible(true);
int result = JOptionPane.CANCEL_OPTION;
Integer value = (Integer) optionPane.getValue();
if (value != null && value != -1) {
result = value;
}
isOK = (result != JOptionPane.CANCEL_OPTION);
if (isOK) {
taxonSet.setID(id);
List<Taxon> taxa = taxonSet.taxonsetInput.get();
while (taxa.size() > 0) {
taxa.remove(0);
}
for (int i = 0; i < listModel2.size(); i++) {
taxa.add(listModel2.get(i));
}
isOK = true;
dispose();
}
return isOK;
}
private Component createFilterBox() {
Box box = Box.createHorizontalBox();
JLabel label = new JLabel("Filter:");
box.add(label);
filterEntry = new JTextField();
filterEntry.setColumns(17);
//Dimension size = new Dimension(100, 20);
//filterEntry.setMinimumSize(size);
//filterEntry.setPreferredSize(size);
//filterEntry.setSize(size);
filterEntry.setToolTipText("Enter regular expression to match taxa");
int fontsize = filterEntry.getFont().getSize();
filterEntry.setMaximumSize(new Dimension(1024 * fontsize / 13, 50 * fontsize / 13));
box.add(filterEntry);
box.add(Box.createHorizontalGlue());
filterEntry.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
processEntry();
}
@Override
public void insertUpdate(DocumentEvent e) {
processEntry();
}
@Override
public void changedUpdate(DocumentEvent e) {
processEntry();
}
});
return box;
}
private void processEntry() {
String filter = ".*" + filterEntry.getText() + ".*";
listModel1.clear();
for (Taxon taxon : _candidates) {
if (taxon.getID().matches(filter)) {
listModel1.addElement(taxon);
}
}
for (int i = 0; i < listModel2.size(); i++) {
listModel1.removeElement(listModel2.get(i));
}
}
Component createIDBox() {
Box box = Box.createHorizontalBox();
box.add(new JLabel("Taxon set label:"));
idEntry = new JTextField();
idEntry.setName("idEntry");
idEntry.setText(id);
box.add(idEntry);
idEntry.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
id = idEntry.getText();
}
@Override
public void insertUpdate(DocumentEvent e) {
id = idEntry.getText();
}
@Override
public void changedUpdate(DocumentEvent e) {
id = idEntry.getText();
}
});
int fontsize = idEntry.getFont().getSize();
box.setMaximumSize(new Dimension(400 * fontsize / 13, 100 * fontsize / 13));
return box;
}
class TaxonCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 1L;
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
JLabel label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
label.setText(((Taxon)value).getID());
return label;
}
}
Component createTaxonSelector() {
Box box = Box.createHorizontalBox();
// list of taxa to select from
listModel1 = new DefaultListModel<>();
listOfTaxonCandidates = new JList<>(listModel1);
listOfTaxonCandidates.setName("listOfTaxonCandidates");
listOfTaxonCandidates.setBorder(BorderFactory.createEtchedBorder());
listOfTaxonCandidates.setCellRenderer(new TaxonCellRenderer());
JScrollPane scroller = new JScrollPane(listOfTaxonCandidates);
box.add(scroller);
// add buttons to select/deselect taxa
Box buttonBox = Box.createVerticalBox();
buttonBox.add(Box.createGlue());
JButton selectButton = new JButton(">>");
selectButton.setName(">>");
selectButton.addActionListener(e -> {
int[] selected = listOfTaxonCandidates.getSelectedIndices();
for (int i : selected) {
listModel2.addElement(listModel1.get(i));
}
for (int i = 0; i < listModel2.size(); i++) {
listModel1.removeElement(listModel2.get(i));
}
});
buttonBox.add(selectButton);
JButton deselectButton = new JButton("<<");
deselectButton.setName("<<");
deselectButton.addActionListener(e -> {
int[] selected = listOfTaxonSet.getSelectedIndices();
for (int i : selected) {
listModel1.addElement(listModel2.get(i));
}
for (int i = 0; i < listModel1.size(); i++) {
listModel2.removeElement(listModel1.get(i));
}
});
buttonBox.add(deselectButton);
buttonBox.add(Box.createGlue());
box.add(buttonBox);
// list of taxa in taxon set
listModel2 = new DefaultListModel<>();
listOfTaxonSet = new JList<>(listModel2);
listOfTaxonSet.setBorder(BorderFactory.createEtchedBorder());
listOfTaxonSet.setCellRenderer(new TaxonCellRenderer());
JScrollPane scroller2 = new JScrollPane(listOfTaxonSet);
box.add(scroller2);
return box;
} // createTaxonSelector
Component createCancelOKButtons() {
Box cancelOkBox = Box.createHorizontalBox();
cancelOkBox.setBorder(new EtchedBorder());
JButton okButton = new JButton("Ok");
okButton.setName("OK");
okButton.addActionListener(e -> {
taxonSet.setID(id);
List<Taxon> taxa = taxonSet.taxonsetInput.get();
while (taxa.size() > 0) {
taxa.remove(0);
}
for (int i = 0; i < listModel2.size(); i++) {
taxa.add(listModel2.get(i));
}
isOK = true;
dispose();
});
JButton cancelButton = new JButton("Cancel");
cancelButton.setName("Cancel");
cancelButton.addActionListener(e -> {
dispose();
});
cancelOkBox.add(Box.createHorizontalGlue());
cancelOkBox.add(okButton);
cancelOkBox.add(Box.createHorizontalGlue());
cancelOkBox.add(cancelButton);
cancelOkBox.add(Box.createHorizontalGlue());
return cancelOkBox;
} // createCancelOKButtons
} // class TaxonSetDialog