/* * TaxonSetsPanel.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.app.treestat; import jam.framework.Exportable; import jam.table.TableRenderer; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.util.ArrayList; public class TaxonSetsPanel extends JPanel implements Exportable { /** * */ private static final long serialVersionUID = -9013475414423166476L; TreeStatFrame frame = null; TreeStatData treeStatData = null; TreeStatData.TaxonSet selectedTaxonSet = null; JScrollPane scrollPane1 = null; JTable taxonSetsTable = null; TaxonSetsTableModel taxonSetsTableModel = null; JScrollPane scrollPane2 = null; JTable excludedTaxaTable = null; TaxaTableModel excludedTaxaTableModel = null; JScrollPane scrollPane3 = null; JTable includedTaxaTable = null; TaxaTableModel includedTaxaTableModel = null; public TaxonSetsPanel(TreeStatFrame frame, TreeStatData treeStatData) { this.frame = frame; setOpaque(false); this.treeStatData = treeStatData; Icon addIcon = null, removeIcon = null, includeIcon = null, excludeIcon = null; try { addIcon = new ImageIcon(dr.app.util.Utils.getImage(this, "images/add.png")); removeIcon = new ImageIcon(dr.app.util.Utils.getImage(this, "images/minus.png")); includeIcon = new ImageIcon(dr.app.util.Utils.getImage(this, "images/include.png")); excludeIcon = new ImageIcon(dr.app.util.Utils.getImage(this, "images/exclude.png")); } catch (Exception e) { // do nothing } JPanel buttonPanel = new JPanel(new BorderLayout()); buttonPanel.setOpaque(false); JButton importButton = new JButton(frame.getImportAction()); importButton.setFocusable(false); importButton.putClientProperty("JButton.buttonType", "textured"); importButton.setMargin(new Insets(4,4,4,4)); buttonPanel.add(importButton, BorderLayout.WEST); buttonPanel.add(new JLabel(" To define taxon sets, first import a list of taxa (i.e., from the trees to be analysed)"), BorderLayout.SOUTH); // Taxon Sets taxonSetsTableModel = new TaxonSetsTableModel(); TableSorter sorter = new TableSorter(taxonSetsTableModel); taxonSetsTable = new JTable(sorter); sorter.addTableModelListener(taxonSetsTable); taxonSetsTable.getColumnModel().getColumn(0).setCellRenderer( new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4))); taxonSetsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { taxonSetsTableSelectionChanged(); } }); scrollPane1 = new JScrollPane(taxonSetsTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); JPanel buttonPanel1 = createAddRemoveButtonPanel(addTaxonSetAction, addIcon, "Create a new taxon set", removeTaxonSetAction, removeIcon, "Remove a taxon set", javax.swing.BoxLayout.X_AXIS); // Excluded Taxon List excludedTaxaTableModel = new TaxaTableModel(false); sorter = new TableSorter(excludedTaxaTableModel); excludedTaxaTable = new JTable(sorter); sorter.addTableModelListener(excludedTaxaTable); excludedTaxaTable.getColumnModel().getColumn(0).setCellRenderer( new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4))); excludedTaxaTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { excludedTaxaTableSelectionChanged(); } }); scrollPane2 = new JScrollPane(excludedTaxaTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); JPanel buttonPanel2 = createAddRemoveButtonPanel(includeTaxonAction, includeIcon, "Include selected taxa in the taxon set", excludeTaxonAction, excludeIcon, "Exclude selected taxa from the taxon set", javax.swing.BoxLayout.Y_AXIS); // Included Taxon List includedTaxaTableModel = new TaxaTableModel(true); sorter = new TableSorter(includedTaxaTableModel); includedTaxaTable = new JTable(sorter); sorter.addTableModelListener(includedTaxaTable); includedTaxaTable.getColumnModel().getColumn(0).setCellRenderer( new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4))); includedTaxaTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { includedTaxaTableSelectionChanged(); } }); scrollPane3 = new JScrollPane(includedTaxaTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); JPanel panel = new JPanel(); panel.setOpaque(false); panel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.weightx = 0.333333; c.weighty = 1; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.insets = new Insets(6,6,6,6); c.gridx = 0; c.gridy = 0; panel.add(scrollPane1, c); c.weightx = 0.333333; c.weighty = 0; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = new Insets(0,6,6,6); c.gridx = 0; c.gridy = 1; panel.add(buttonPanel1, c); c.weightx = 0.333333; c.weighty = 1; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.insets = new Insets(6,6,6,6); c.gridx = 1; c.gridy = 0; panel.add(scrollPane2, c); c.weightx = 0.0; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; c.insets = new Insets(0,0,0,0); c.gridx = 2; c.gridy = 0; panel.add(buttonPanel2, c); c.weightx = 0.333333; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.insets = new Insets(6,6,6,6); c.gridx = 3; c.gridy = 0; panel.add(scrollPane3, c); setLayout(new BorderLayout()); setBorder(BorderFactory.createEmptyBorder(6,6,6,6)); add(buttonPanel, BorderLayout.NORTH); add(panel, BorderLayout.CENTER); } JPanel createAddRemoveButtonPanel(Action addAction, Icon addIcon, String addToolTip, Action removeAction, Icon removeIcon, String removeToolTip, int axis) { JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, axis)); buttonPanel.setOpaque(false); JButton addButton = new JButton(addAction); if (addIcon != null) { addButton.setIcon(addIcon); addButton.setText(null); } addButton.setToolTipText(addToolTip); addButton.putClientProperty("JButton.buttonType", "textured"); addButton.setOpaque(false); addAction.setEnabled(false); JButton removeButton = new JButton(removeAction); if (removeIcon != null) { removeButton.setIcon(removeIcon); removeButton.setText(null); } removeButton.setToolTipText(removeToolTip); removeButton.putClientProperty("JButton.buttonType", "textured"); removeButton.setOpaque(false); removeAction.setEnabled(false); buttonPanel.add(addButton); buttonPanel.add(new JToolBar.Separator(new Dimension(6,6))); buttonPanel.add(removeButton); return buttonPanel; } public void dataChanged() { addTaxonSetAction.setEnabled(treeStatData.allTaxa.size() > 0); taxonSetsTableModel.fireTableDataChanged(); includedTaxaTableModel.fireTableDataChanged(); excludedTaxaTableModel.fireTableDataChanged(); } private void taxonSetsTableSelectionChanged() { if (taxonSetsTable.getSelectedRowCount() == 0) { selectedTaxonSet = null; removeTaxonSetAction.setEnabled(false); } else { selectedTaxonSet = treeStatData.taxonSets.get(taxonSetsTable.getSelectedRow()); removeTaxonSetAction.setEnabled(true); } includedTaxaTableModel.fireTableDataChanged(); excludedTaxaTableModel.fireTableDataChanged(); } private void excludedTaxaTableSelectionChanged() { if (excludedTaxaTable.getSelectedRowCount() == 0) { includeTaxonAction.setEnabled(false); } else { includeTaxonAction.setEnabled(true); } } private void includedTaxaTableSelectionChanged() { if (includedTaxaTable.getSelectedRowCount() == 0) { excludeTaxonAction.setEnabled(false); } else { excludeTaxonAction.setEnabled(true); } } public JComponent getExportableComponent() { return this; } Action addTaxonSetAction = new AbstractAction("+") { /** * */ private static final long serialVersionUID = 1831933175582860833L; public void actionPerformed(ActionEvent ae) { TreeStatData.TaxonSet taxonSet = new TreeStatData.TaxonSet(); taxonSet.name = "untitled"; taxonSet.taxa = new ArrayList(); treeStatData.taxonSets.add(taxonSet); dataChanged(); int sel = treeStatData.taxonSets.size() - 1; taxonSetsTable.setRowSelectionInterval(sel, sel); } }; Action removeTaxonSetAction = new AbstractAction("-") { /** * */ private static final long serialVersionUID = -8662527333546044639L; public void actionPerformed(ActionEvent ae) { int saved = taxonSetsTable.getSelectedRow(); int row = taxonSetsTable.getSelectedRow(); if (row != -1) { treeStatData.taxonSets.remove(row); } dataChanged(); if (saved >= treeStatData.taxonSets.size()) saved = treeStatData.taxonSets.size() - 1; taxonSetsTable.setRowSelectionInterval(saved, saved); } }; Action includeTaxonAction = new AbstractAction("->") { /** * */ private static final long serialVersionUID = -1875904513948242608L; public void actionPerformed(ActionEvent ae) { int saved = taxonSetsTable.getSelectedRow(); int[] rows = excludedTaxaTable.getSelectedRows(); ArrayList<String> exclList = new ArrayList<String>(treeStatData.allTaxa); exclList.removeAll(selectedTaxonSet.taxa); for (int row : rows) { selectedTaxonSet.taxa.add(exclList.get(row)); } dataChanged(); taxonSetsTable.setRowSelectionInterval(saved, saved); } }; Action excludeTaxonAction = new AbstractAction("<-") { /** * */ private static final long serialVersionUID = 4523480086490780822L; public void actionPerformed(ActionEvent ae) { int saved = taxonSetsTable.getSelectedRow(); int[] rows = includedTaxaTable.getSelectedRows(); for (int i = rows.length - 1; i >= 0 ; i--) { selectedTaxonSet.taxa.remove(rows[i]); } dataChanged(); taxonSetsTable.setRowSelectionInterval(saved, saved); } }; class TaxonSetsTableModel extends AbstractTableModel { /** * */ private static final long serialVersionUID = 219223813257870207L; public TaxonSetsTableModel() { } public int getColumnCount() { return 1; } public int getRowCount() { return treeStatData.taxonSets.size(); } public Object getValueAt(int row, int col) { return (treeStatData.taxonSets.get(row)).name; } public void setValueAt(Object value, int row, int col) { (treeStatData.taxonSets.get(row)).name = (String)value; } public boolean isCellEditable(int row, int col) { return true; } public String getColumnName(int column) { return "Taxon Sets"; } public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} } class TaxaTableModel extends AbstractTableModel { /** * */ private static final long serialVersionUID = 1559408662356843275L; boolean included; public TaxaTableModel(boolean included) { this.included = included; } public int getColumnCount() { return 1; } public int getRowCount() { if (selectedTaxonSet == null) return 0; if (included) { return selectedTaxonSet.taxa.size(); } else { return treeStatData.allTaxa.size() - selectedTaxonSet.taxa.size(); } } public Object getValueAt(int row, int col) { if (included) { return selectedTaxonSet.taxa.get(row); } else { ArrayList<String> exclList = new ArrayList<String>(treeStatData.allTaxa); exclList.removeAll(selectedTaxonSet.taxa); return exclList.get(row); } } public boolean isCellEditable(int row, int col) { return false; } public String getColumnName(int column) { if (included) return "Included Taxa"; else return "Excluded Taxa"; } public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} } }