package com.compomics.util.gui.genes; import com.compomics.util.examples.BareBonesBrowserLaunch; import com.compomics.util.experiment.biology.genes.GeneMaps; import com.compomics.util.experiment.identification.matches.ProteinMatch; import java.awt.Component; import java.awt.event.MouseEvent; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.ScrollPaneConstants; import javax.swing.border.TitledBorder; import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import no.uib.jsparklines.extra.HtmlLinksRenderer; /** * This dialog displays the gene details associated to a protein match. * * @author Marc Vaudel * @author Harald Barsnes */ public class GeneDetailsDialog extends javax.swing.JDialog { /** * The Gene maps. */ private GeneMaps geneMaps; /** * The protein accessions of this match. */ private ArrayList<String> proteinAccessions = new ArrayList<String>(); /** * The protein accession column in the table. Only used if more than one * accession. */ private ArrayList<String> proteinAccessionColumn = new ArrayList<String>(); /** * The GO term descriptions attached to this protein match. */ private ArrayList<String> goTermDescriptions; /** * The color to use for the HTML tags for the selected rows, in HTML color * code. */ private String selectedRowHtmlTagFontColor = "#FFFFFF"; // @TODO: move somewhere more generic... /** * The color to use for the HTML tags for the rows that are not selected, in * HTML color code. */ private String notSelectedRowHtmlTagFontColor = "#0101DF"; // @TODO: move somewhere more generic... /** * Creates a new GeneDetailsDialog. * * @param parent the parent frame * @param proteinMatchKey the protein match key * @param geneMaps the gene maps * * @throws java.io.IOException exception thrown whenever an error occurred * while reading the FASTA file. * @throws java.lang.InterruptedException exception thrown whenever an error * occurred while waiting for the connection to the FASTA file to recover. */ public GeneDetailsDialog(java.awt.Frame parent, String proteinMatchKey, GeneMaps geneMaps) throws IOException, InterruptedException { super(parent, true); initComponents(); this.geneMaps = geneMaps; proteinAccessions = new ArrayList<String>(Arrays.asList(ProteinMatch.getAccessions(proteinMatchKey))); goTable.setModel(new GOTableModel()); if (geneMaps != null) { goTermDescriptions = new ArrayList<String>(); if (proteinAccessions.size() == 1) { goTermDescriptions = new ArrayList<String>(geneMaps.getGoNamesForProtein(proteinMatchKey)); Collections.sort(goTermDescriptions); } else { for (String accession : proteinAccessions) { HashSet<String> tempGoNameAccessions = geneMaps.getGoNamesForProtein(accession); ArrayList<String> tempGoNameAccessionsArray = new ArrayList<String>(); tempGoNameAccessionsArray.addAll(tempGoNameAccessions); Collections.sort(tempGoNameAccessionsArray); goTermDescriptions.addAll(tempGoNameAccessionsArray); for (int i = 0; i < tempGoNameAccessionsArray.size(); i++) { proteinAccessionColumn.add(accession); } } } } else { goTermDescriptions = new ArrayList<String>(0); } setUpGUI(); setLocationRelativeTo(parent); setVisible(true); } /** * Set up the GUI. * * @throws java.io.IOException exception thrown whenever an error occurred * while reading the FASTA file * @throws java.lang.InterruptedException exception thrown whenever an error * occurred while waiting for the connection to the FASTA file to recover */ private void setUpGUI() throws IOException, InterruptedException { goTable.getColumn("Accession").setCellRenderer(new HtmlLinksRenderer(selectedRowHtmlTagFontColor, notSelectedRowHtmlTagFontColor)); // set the preferred size of the accession column Integer width = getPreferredAccessionColumnWidth(goTable, goTable.getColumn("Accession").getModelIndex(), 20); if (width != null) { goTable.getColumn("Accession").setMinWidth(width); goTable.getColumn("Accession").setMaxWidth(width); } else { goTable.getColumn("Accession").setMinWidth(15); goTable.getColumn("Accession").setMaxWidth(Integer.MAX_VALUE); } if (proteinAccessions.size() > 1) { width = getPreferredAccessionColumnWidth(goTable, goTable.getColumn("Protein").getModelIndex(), 20); if (width != null) { goTable.getColumn("Protein").setMinWidth(width); goTable.getColumn("Protein").setMaxWidth(width); } else { goTable.getColumn("Protein").setMinWidth(15); goTable.getColumn("Protein").setMaxWidth(Integer.MAX_VALUE); } } goTable.getColumn(" ").setMaxWidth(50); goTable.getColumn(" ").setMinWidth(50); goTable.getTableHeader().setReorderingAllowed(false); goTable.setAutoCreateRowSorter(true); // correct the color for the upper right corner JPanel proteinCorner = new JPanel(); proteinCorner.setBackground(goTable.getTableHeader().getBackground()); goTableScrollPane.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, proteinCorner); // make sure that the scroll panes are see-through goTableScrollPane.getViewport().setOpaque(false); String title = "", geneIdsTxt = "", geneNamesTxt = "", chromosomeTxt = ""; ArrayList<String> geneNames = new ArrayList<String>(); for (String accession : proteinAccessions) { if (title.isEmpty()) { title += "Gene details for "; } else { title += ", "; } title += accession; String geneName = geneMaps.getGeneNameForProtein(accession); geneNames.add(geneName); } ArrayList<String> chromosomes = new ArrayList<String>(); for (String geneName : geneNames) { if (!geneIdsTxt.equals("")) { geneIdsTxt += ", "; geneNamesTxt += ", "; } if (geneName == null) { geneNamesTxt += "unknown"; geneIdsTxt += "unknown"; } else { String ensemblId = geneMaps.getEnsemblId(geneName); if (ensemblId == null) { geneIdsTxt += "unknown"; } else { geneIdsTxt += ensemblId; } geneNamesTxt += geneName; String chromosome = geneMaps.getChromosome(geneName); chromosomes.add(chromosome); } } if (chromosomes.isEmpty()) { chromosomeTxt = "unknown"; } else { for (String chromosome : chromosomes) { if (!chromosomeTxt.equals("")) { chromosomeTxt += ", "; } if (chromosome == null) { chromosomeTxt += "unknown"; } else { chromosomeTxt += chromosome; } } } ((TitledBorder) detailsPanel.getBorder()).setTitle(title); geneIdTxt.setText(geneIdsTxt); geneNameTxt.setText(geneNamesTxt); chromosomeNameTxt.setText(chromosomeTxt); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { backgroundPanel = new javax.swing.JPanel(); detailsPanel = new javax.swing.JPanel(); ensemlbIdLabel = new javax.swing.JLabel(); geneIdTxt = new javax.swing.JTextField(); geneNameTxt = new javax.swing.JTextField(); geneNameLabel = new javax.swing.JLabel(); chromosomeLabel = new javax.swing.JLabel(); chromosomeNameTxt = new javax.swing.JTextField(); goAnnotationLabel = new javax.swing.JLabel(); goTableScrollPane = new javax.swing.JScrollPane(); goTable = new javax.swing.JTable(); okButton = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle("Gene Details"); backgroundPanel.setBackground(new java.awt.Color(230, 230, 230)); detailsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Gene Details")); detailsPanel.setOpaque(false); ensemlbIdLabel.setText("Ensembl Gene ID"); geneIdTxt.setEditable(false); geneNameTxt.setEditable(false); geneNameLabel.setText("Gene Name"); chromosomeLabel.setText("Chromosome"); chromosomeNameTxt.setEditable(false); goAnnotationLabel.setText("GO Annotation"); goTable.setModel(new GOTableModel()); goTable.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseReleased(java.awt.event.MouseEvent evt) { goTableMouseReleased(evt); } public void mouseExited(java.awt.event.MouseEvent evt) { goTableMouseExited(evt); } }); goTable.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { public void mouseMoved(java.awt.event.MouseEvent evt) { goTableMouseMoved(evt); } }); goTableScrollPane.setViewportView(goTable); javax.swing.GroupLayout detailsPanelLayout = new javax.swing.GroupLayout(detailsPanel); detailsPanel.setLayout(detailsPanelLayout); detailsPanelLayout.setHorizontalGroup( detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(detailsPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(goTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 707, Short.MAX_VALUE) .addGroup(detailsPanelLayout.createSequentialGroup() .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(ensemlbIdLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(geneNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(geneNameTxt) .addComponent(geneIdTxt))) .addGroup(detailsPanelLayout.createSequentialGroup() .addComponent(goAnnotationLabel) .addGap(0, 0, Short.MAX_VALUE)) .addGroup(detailsPanelLayout.createSequentialGroup() .addComponent(chromosomeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(chromosomeNameTxt))) .addContainerGap()) ); detailsPanelLayout.setVerticalGroup( detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(detailsPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(ensemlbIdLabel) .addComponent(geneIdTxt, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(geneNameLabel) .addComponent(geneNameTxt, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(chromosomeLabel) .addComponent(chromosomeNameTxt, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(18, 18, 18) .addComponent(goAnnotationLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(goTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 206, Short.MAX_VALUE) .addContainerGap()) ); okButton.setText("OK"); okButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { okButtonActionPerformed(evt); } }); javax.swing.GroupLayout backgroundPanelLayout = new javax.swing.GroupLayout(backgroundPanel); backgroundPanel.setLayout(backgroundPanelLayout); backgroundPanelLayout.setHorizontalGroup( backgroundPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(backgroundPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(backgroundPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(detailsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, backgroundPanelLayout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); backgroundPanelLayout.setVerticalGroup( backgroundPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, backgroundPanelLayout.createSequentialGroup() .addContainerGap() .addComponent(detailsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(okButton) .addContainerGap()) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(backgroundPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(backgroundPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); pack(); }// </editor-fold>//GEN-END:initComponents /** * Close the dialog. * * @param evt */ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed dispose(); }//GEN-LAST:event_okButtonActionPerformed /** * If the user clicks the GO accession column the GO term is opened in the * web browser. * * @param evt */ private void goTableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_goTableMouseReleased int row = goTable.getSelectedRow(); int column = goTable.getSelectedColumn(); if (row != -1) { this.setCursor(new java.awt.Cursor(java.awt.Cursor.WAIT_CURSOR)); if (evt != null && evt.getButton() == MouseEvent.BUTTON1) { // open protein link in web browser if (column == goTable.getColumn("Accession").getModelIndex() && ((String) goTable.getValueAt(row, column)).lastIndexOf("<html>") != -1) { String link = (String) goTable.getValueAt(row, column); link = link.substring(link.indexOf("\"") + 1); link = link.substring(0, link.indexOf("\"")); this.setCursor(new java.awt.Cursor(java.awt.Cursor.WAIT_CURSOR)); BareBonesBrowserLaunch.openURL(link); this.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); } } this.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); } }//GEN-LAST:event_goTableMouseReleased /** * Changes the cursor into a hand cursor if the table cell contains an HTML * link. * * @param evt */ private void goTableMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_goTableMouseMoved int row = goTable.rowAtPoint(evt.getPoint()); int column = goTable.columnAtPoint(evt.getPoint()); if (column == goTable.getColumn("Accession").getModelIndex() && goTable.getValueAt(row, column) != null) { String tempValue = (String) goTable.getValueAt(row, column); if (tempValue.lastIndexOf("<html>") != -1) { this.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); } else { this.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); } } else { this.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); } }//GEN-LAST:event_goTableMouseMoved /** * Changes the cursor back to the default cursor a hand. * * @param evt */ private void goTableMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_goTableMouseExited this.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); }//GEN-LAST:event_goTableMouseExited // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel backgroundPanel; private javax.swing.JLabel chromosomeLabel; private javax.swing.JTextField chromosomeNameTxt; private javax.swing.JPanel detailsPanel; private javax.swing.JLabel ensemlbIdLabel; private javax.swing.JTextField geneIdTxt; private javax.swing.JLabel geneNameLabel; private javax.swing.JTextField geneNameTxt; private javax.swing.JLabel goAnnotationLabel; private javax.swing.JTable goTable; private javax.swing.JScrollPane goTableScrollPane; private javax.swing.JButton okButton; // End of variables declaration//GEN-END:variables /** * Table model for the GO annotation. */ private class GOTableModel extends DefaultTableModel { @Override public int getRowCount() { if (goTermDescriptions != null) { return goTermDescriptions.size(); } return 0; } @Override public int getColumnCount() { if (proteinAccessions.size() > 1) { return 4; } else { return 3; } } @Override public String getColumnName(int column) { if (proteinAccessions.size() > 1) { switch (column) { case 0: return " "; case 1: return "Protein"; case 2: return "Accession"; case 3: return "Description"; default: return ""; } } else { switch (column) { case 0: return " "; case 1: return "Accession"; case 2: return "Description"; default: return ""; } } } @Override public Object getValueAt(int row, int column) { if (proteinAccessions.size() > 1) { switch (column) { case 0: return (row + 1); case 1: return proteinAccessionColumn.get(row); // @TODO: add database link (requires the DisplayFeaturesGenerator...) case 2: try { String goAccession = geneMaps.getGoAccession(goTermDescriptions.get(row)); if (goAccession != null) { return addGoLink(goAccession); } else { return ""; } } catch (Exception e) { return "Error"; } case 3: try { return goTermDescriptions.get(row); } catch (Exception e) { return "Error"; } default: return ""; } } else { switch (column) { case 0: return (row + 1); case 1: try { String goAccession = geneMaps.getGoAccession(goTermDescriptions.get(row)); if (goAccession != null) { return addGoLink(goAccession); } else { return ""; } } catch (Exception e) { return "Error"; } case 2: try { return goTermDescriptions.get(row); } catch (Exception e) { return "Error"; } default: return ""; } } } @Override public Class getColumnClass(int columnIndex) { return getValueAt(0, columnIndex).getClass(); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } } /** * Returns the GO accession number as a web link to the given GO term at * QuickGO. * * @param goAccession the GO accession * @return the GO accession number as a web link to the given GO term at * QuickGO */ public String addGoLink(String goAccession) { return "<html><a href=\"" + getGoAccessionLink(goAccession) + "\"><font color=\"" + notSelectedRowHtmlTagFontColor + "\">" + goAccession + "</font></a></html>"; } /** * Returns the GO accession number as a web link to the given GO term at * QuickGO. * * @param goAccession the GO accession number * @return the GO accession web link */ public String getGoAccessionLink(String goAccession) { return "http://www.ebi.ac.uk/QuickGO/GTerm?id=" + goAccession; } /** * Gets the preferred width of the column specified by colIndex. The column * will be just wide enough to show the column head and the widest cell in * the column. Margin pixels are added to the left and right (resulting in * an additional width of 2*margin pixels. Returns null if the max width * cannot be set. * * @param table the table * @param colIndex the colum index * @param margin the margin to add * @return the preferred width of the column */ public Integer getPreferredAccessionColumnWidth(JTable table, int colIndex, int margin) { DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel(); TableColumn col = colModel.getColumn(colIndex); // get width of column header TableCellRenderer renderer = col.getHeaderRenderer(); if (renderer == null) { renderer = table.getTableHeader().getDefaultRenderer(); } Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0); int width = comp.getPreferredSize().width; // add margin width += 2 * margin; return width; } }