package org.phenoscape.view; import java.awt.BorderLayout; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.util.Collection; import java.util.Comparator; import javax.swing.AbstractAction; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.obo.annotation.view.TermAutocompleteFieldFactory; import org.obo.annotation.view.TermRenderer; import org.obo.app.swing.BugWorkaroundTable; import org.obo.app.swing.PlaceholderRenderer; import org.obo.app.swing.SortDisabler; import org.obo.app.swing.TableColumnPrefsSaver; import org.obo.datamodel.LinkedObject; import org.obo.datamodel.OBOClass; import org.obo.datamodel.OBOObject; import org.obo.datamodel.PropertyValue; import org.obo.util.TermUtil; import org.phenoscape.controller.PhenexController; import org.phenoscape.model.Taxon; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.GlazedLists; import ca.odell.glazedlists.gui.AdvancedTableFormat; import ca.odell.glazedlists.gui.WritableTableFormat; import ca.odell.glazedlists.swing.EventTableModel; import ca.odell.glazedlists.swing.TableComparatorChooser; import com.eekboom.utils.Strings; public class TaxonTableComponent extends PhenoscapeGUIComponent { private JButton addTaxonButton; private JButton deleteTaxonButton; private EventTableModel<Taxon> taxaTableModel; public TaxonTableComponent(String id, PhenexController controller) { super(id, controller); } @Override public void init() { super.init(); this.initializeInterface(); } public void copy() { final StringBuffer buffer = new StringBuffer(); final int columnCount = this.taxaTableModel.getColumnCount(); for (int row = 0; row < this.getController().getSortedTaxa().size(); row++) { if (this.getController().getTaxaSelectionModel().isSelectedIndex(row)) { for (int column = 0; column < columnCount; column++) { final Object value = this.taxaTableModel.getValueAt(row, column); buffer.append(value != null ? value : ""); if ((column + 1) < columnCount) { buffer.append("\t"); } } buffer.append(System.getProperty("line.separator")); } } if (buffer.length() > 0) { final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); final StringSelection stringSelection = new StringSelection(buffer.toString()); clipboard.setContents(stringSelection, null); } } private void addTaxon() { this.getController().getDataSet().newTaxon(); } private void deleteSelectedTaxon() { final Taxon taxon = this.getSelectedTaxon(); if (taxon != null) { this.getController().getDataSet().removeTaxon(taxon); } } private Taxon getSelectedTaxon() { final EventList<Taxon> selected = this.getController().getTaxaSelectionModel().getSelected(); if (selected.size() == 1) { return selected.get(0); } else { return null; } } private void updateButtonStates() { this.deleteTaxonButton.setEnabled(this.getSelectedTaxon() != null); } private void selectFirstSpecimen() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (!getController().getSpecimensForCurrentTaxonSelection().isEmpty()) { getController().getCurrentSpecimensSelectionModel().setSelectionInterval(0, 0); } } }); } private void initializeInterface() { this.setLayout(new BorderLayout()); this.taxaTableModel = new EventTableModel<Taxon>(this.getController().getSortedTaxa(), new TaxaTableFormat()); final JTable taxaTable = new BugWorkaroundTable(this.taxaTableModel); taxaTable.setSelectionModel(this.getController().getTaxaSelectionModel()); taxaTable.setDefaultRenderer(Object.class, new PlaceholderRenderer("None")); taxaTable.setDefaultRenderer(OBOObject.class, new TermRenderer("None")); taxaTable.getColumnModel().getColumn(1).setCellEditor(TermAutocompleteFieldFactory.createAutocompleteEditor(this.getController().getOntologyController().getTaxonTermSet(), getController().getOntologyCoordinator())); taxaTable.putClientProperty("Quaqua.Table.style", "striped"); taxaTable.getActionMap().getParent().remove("copy"); taxaTable.getActionMap().getParent().remove("paste"); new TableColumnPrefsSaver(taxaTable, this.getClass().getName()); final TableComparatorChooser<Taxon> sortChooser = new TableComparatorChooser<Taxon>(taxaTable, this.getController().getSortedTaxa(), false); sortChooser.addSortActionListener(new SortDisabler()); this.add(new JScrollPane(taxaTable), BorderLayout.CENTER); this.add(this.createToolBar(), BorderLayout.NORTH); this.getController().getTaxaSelectionModel().addListSelectionListener(new TaxonSelectionListener()); } private JToolBar createToolBar() { final JToolBar toolBar = new JToolBar(); this.addTaxonButton = new JButton(new AbstractAction(null, new ImageIcon(this.getClass().getResource("/org/phenoscape/view/images/list-add.png"))) { @Override public void actionPerformed(ActionEvent e) { addTaxon(); } }); this.addTaxonButton.setToolTipText("Add Taxon"); toolBar.add(this.addTaxonButton); this.deleteTaxonButton = new JButton(new AbstractAction(null, new ImageIcon(this.getClass().getResource("/org/phenoscape/view/images/list-remove.png"))) { @Override public void actionPerformed(ActionEvent e) { deleteSelectedTaxon(); } }); this.deleteTaxonButton.setToolTipText("Delete Taxon"); toolBar.add(this.deleteTaxonButton); toolBar.setFloatable(false); return toolBar; } private OBOObject getFamilyForTaxon(OBOClass taxon) { final Collection<LinkedObject> ancestors = TermUtil.getisaAncestors(taxon, true); for (LinkedObject ancestor : ancestors) { for (PropertyValue value : ancestor.getPropertyValues()) { if (value.getValue().equals("has_rank TAXRANK:0000004") && value.getProperty().equals("property_value")) { return (OBOObject)ancestor; } } } return null; } private class TaxaTableFormat implements WritableTableFormat<Taxon>, AdvancedTableFormat<Taxon> { @Override public boolean isEditable(Taxon taxon, int column) { return column != 0 || column != 6; } @Override public Taxon setColumnValue(Taxon taxon, Object editedValue, int column) { switch (column) { case 0: break; case 1: taxon.setValidName((OBOClass)editedValue); break; case 2: taxon.setPublicationName(editedValue.toString()); break; case 3: taxon.setComment(editedValue.toString()); break; case 4: taxon.setMatrixTaxonName(editedValue.toString()); break; case 5: taxon.setFigure(editedValue.toString()); break; case 6: break; } return taxon; } @Override public int getColumnCount() { return 7; } @Override public String getColumnName(int column) { switch (column) { case 0: return " "; case 1: return "Valid Taxon"; case 2: return "Publication Taxon"; case 3: return "Comment"; case 4: return "Matrix Taxon"; case 5: return "Figure"; case 6: return "Family"; default: return null; } } @Override public Object getColumnValue(Taxon taxon, int column) { switch (column) { case 0: return getController().getDataSet().getTaxa().indexOf(taxon) + 1; case 1: return taxon.getValidName(); case 2: return taxon.getPublicationName(); case 3: return taxon.getComment(); case 4: return taxon.getMatrixTaxonName(); case 5: return taxon.getFigure(); case 6: return taxon.getValidName() != null ? getFamilyForTaxon(taxon.getValidName()) : null; default: return null; } } @Override public Class<?> getColumnClass(int column) { switch (column) { case 0: return Integer.class; case 1: return OBOObject.class; case 2: return String.class; case 3: return String.class; case 4: return String.class; case 5: return String.class; case 6: return OBOObject.class; default: return null; } } @Override public Comparator<?> getColumnComparator(int column) { switch (column) { case 0: return GlazedLists.comparableComparator(); case 1: return GlazedLists.comparableComparator(); case 2: return Strings.getNaturalComparator(); case 3: return Strings.getNaturalComparator(); case 4: return Strings.getNaturalComparator(); case 5: return Strings.getNaturalComparator(); case 6: return GlazedLists.comparableComparator(); default: return null; } } } private class TaxonSelectionListener implements ListSelectionListener { public TaxonSelectionListener() { updateButtonStates(); } @Override public void valueChanged(ListSelectionEvent e) { updateButtonStates(); selectFirstSpecimen(); } } }