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