/* * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5) * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * * Jalview 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along with Jalview. If not, see . */ package jalview.gui; import java.util.regex.*; import java.util.*; import java.awt.*; import javax.swing.*; import javax.swing.event.*; import java.awt.event.*; import java.io.*; import jalview.jbgui.GStructureViewer; import jalview.api.SequenceStructureBinding; import jalview.bin.Cache; import jalview.datamodel.*; import jalview.gui.*; import jalview.structure.*; import jalview.datamodel.PDBEntry; import jalview.io.*; import jalview.schemes.*; import jalview.ws.ebi.EBIFetchClient; import org.jmol.api.*; import org.jmol.adapter.smarter.SmarterJmolAdapter; import org.jmol.popup.*; import org.jmol.viewer.JmolConstants; public class AppJmol extends GStructureViewer implements Runnable, SequenceStructureBinding { AppJmolBinding jmb; ScriptWindow scriptWindow; JSplitPane splitPane; RenderPanel renderPanel; AlignmentPanel ap; Vector atomsPicked = new Vector(); public AppJmol(String file, String id, SequenceI[] seq, AlignmentPanel ap, String loadStatus, Rectangle bounds) { this(file, id, seq, ap, loadStatus, bounds, null); } public AppJmol(String file, String id, SequenceI[] seq, AlignmentPanel ap, String loadStatus, Rectangle bounds, String viewid) { PDBEntry pdbentry = new PDBEntry(); pdbentry.setFile(file); pdbentry.setId(id); // / TODO: check if protocol is needed to be set, and if chains are // autodiscovered. jmb = new AppJmolBinding(this, new PDBEntry[] { pdbentry }, seq, null, null); jmb.setLoadingFromArchive(true); this.ap = ap; this.setBounds(bounds); jmb.setColourBySequence(false); seqColour.setSelected(false); viewId = viewid; // jalview.gui.Desktop.addInternalFrame(this, "Loading File", // bounds.width,bounds.height); this.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameClosing(InternalFrameEvent internalFrameEvent) { closeViewer(); } }); initJmol(loadStatus); // pdbentry, seq, JBPCHECK! } public AppJmol(PDBEntry pdbentry, SequenceI[] seq, String[] chains, AlignmentPanel ap) { // //////////////////////////////// // Is the pdb file already loaded? String alreadyMapped = StructureSelectionManager .getStructureSelectionManager().alreadyMappedToFile( pdbentry.getId()); if (alreadyMapped != null) { int option = JOptionPane .showInternalConfirmDialog( Desktop.desktop, pdbentry.getId() + " is already displayed." + "\nDo you want to re-use this viewer ?", "Map Sequences to Visible Window: " + pdbentry.getId(), JOptionPane.YES_NO_OPTION); if (option == JOptionPane.YES_OPTION) { StructureSelectionManager.getStructureSelectionManager() .setMapping(seq, chains, alreadyMapped, AppletFormatAdapter.FILE); if (ap.seqPanel.seqCanvas.fr != null) { ap.seqPanel.seqCanvas.fr.featuresAdded(); ap.paintAlignment(true); } // Now this AppJmol is mapped to new sequences. We must add them to // the exisiting array JInternalFrame[] frames = Desktop.instance.getAllFrames(); for (int i = 0; i < frames.length; i++) { if (frames[i] instanceof AppJmol) { AppJmol topJmol = ((AppJmol) frames[i]); // JBPNOTE: this looks like a binding routine, rather than a gui // routine for (int pe = 0; pe < topJmol.jmb.pdbentry.length; pe++) { if (topJmol.jmb.pdbentry[pe].getFile().equals(alreadyMapped)) { topJmol.jmb.addSequence(seq); break; } } } } return; } } // ///////////////////////////////// jmb = new AppJmolBinding(this, new PDBEntry[] { pdbentry }, seq, null, null); this.ap = ap; setSize(400, 400); // probably should be a configurable/dynamic default here if (pdbentry.getFile() != null) { initJmol("load \"" + pdbentry.getFile() + "\""); } else { Thread worker = new Thread(this); worker.start(); } this.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameClosing(InternalFrameEvent internalFrameEvent) { closeViewer(); } }); } void initJmol(String command) { jmb.setFinishedInit(false); renderPanel = new RenderPanel(); // TODO: consider waiting until the structure/view is fully loaded before // displaying this.getContentPane().add(renderPanel, java.awt.BorderLayout.CENTER); jalview.gui.Desktop.addInternalFrame(this, jmb.getViewerTitle(), getBounds().width, getBounds().height); jmb.allocateViewer(renderPanel, true, "", null, null, ""); jmb.newJmolPopup(true, "Jmol", true); jmb.evalStateCommand(command); jmb.setFinishedInit(true); } void setChainMenuItems(Vector chains) { chainMenu.removeAll(); if (chains==null) { return; } JMenuItem menuItem = new JMenuItem("All"); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { allChainsSelected = true; for (int i = 0; i < chainMenu.getItemCount(); i++) { if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true); } centerViewer(); allChainsSelected = false; } }); chainMenu.add(menuItem); for (int c = 0; c < chains.size(); c++) { menuItem = new JCheckBoxMenuItem(chains.elementAt(c).toString(), true); menuItem.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent evt) { if (!allChainsSelected) centerViewer(); } }); chainMenu.add(menuItem); } } boolean allChainsSelected = false; void centerViewer() { Vector toshow = new Vector(); String lbl; int mlength, p, mnum; for (int i = 0; i < chainMenu.getItemCount(); i++) { if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) { JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i); if (item.isSelected()) { toshow.addElement(item.getText()); } } } jmb.centerViewer(toshow); } void closeViewer() { jmb.closeViewer(); // TODO: check for memory leaks where instance isn't finalised because jmb // holds a reference to the window jmb = null; } public void run() { String pdbid = ""; // todo - record which pdbids were successfuly imported. StringBuffer errormsgs = new StringBuffer(), files = new StringBuffer(); try { // TODO: replace with reference fetching/transfer code (validate PDBentry // as a DBRef?) jalview.ws.dbsources.Pdb pdbclient = new jalview.ws.dbsources.Pdb(); for (int pi = 0; pi < jmb.pdbentry.length; pi++) { AlignmentI pdbseq; if ((pdbseq = pdbclient.getSequenceRecords(pdbid = jmb.pdbentry[pi] .getId())) != null) { String file; // just transfer the file name from the first sequence's first // PDBEntry jmb.pdbentry[pi].setFile(file = ((PDBEntry) pdbseq.getSequenceAt( 0).getPDBId().elementAt(0)).getFile()); files.append("\"" + file + "\""); } else { errormsgs.append("'" + pdbid + "' "); } } } catch (OutOfMemoryError oomerror) { new OOMWarning("Retrieving PDB id " + pdbid, oomerror); } catch (Exception ex) { ex.printStackTrace(); errormsgs.append("'" + pdbid + "'"); } if (errormsgs.length() > 0) { JOptionPane.showInternalMessageDialog(Desktop.desktop, "The following pdb entries could not be retrieved from the PDB:\n" + errormsgs.toString() + "\nPlease try downloading them manually.", "Couldn't load file", JOptionPane.ERROR_MESSAGE); } if (files.length() > 0) { try { initJmol("load FILES " + files.toString()); } catch (OutOfMemoryError oomerror) { new OOMWarning("When trying to open the Jmol viewer!", oomerror); Cache.log.debug("File locations are " + files); } catch (Exception ex) { Cache.log.error("Couldn't open Jmol viewer!", ex); } } } public void pdbFile_actionPerformed(ActionEvent actionEvent) { JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache .getProperty("LAST_DIRECTORY")); chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle("Save PDB File"); chooser.setToolTipText("Save"); int value = chooser.showSaveDialog(this); if (value == JalviewFileChooser.APPROVE_OPTION) { try { // TODO: cope with multiple PDB files in view BufferedReader in = new BufferedReader(new FileReader(jmb.getPdbFile()[0])); File outFile = chooser.getSelectedFile(); PrintWriter out = new PrintWriter(new FileOutputStream(outFile)); String data; while ((data = in.readLine()) != null) { if (!(data.indexOf("
") > -1 || data.indexOf("
") > -1)) { out.println(data); } } out.close(); } catch (Exception ex) { ex.printStackTrace(); } } } public void viewMapping_actionPerformed(ActionEvent actionEvent) { jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer(); try {for (int pdbe = 0; pdbe20) { lines++; g.drawString(sb.toString(), 20, currentSize.height/2 - lines*g.getFontMetrics().getHeight()); } } } else if (jmb == null || jmb.viewer == null || !jmb.isFinishedInit()) { g.setColor(Color.black); g.fillRect(0, 0, currentSize.width, currentSize.height); g.setColor(Color.white); g.setFont(new Font("Verdana", Font.BOLD, 14)); g.drawString("Retrieving PDB data....", 20, currentSize.height / 2); } else { jmb.viewer.renderScreenImage(g, currentSize, rectClip); } } } String viewId = null; public String getViewId() { if (viewId == null) { viewId = System.currentTimeMillis() + "." + this.hashCode(); } return viewId; } public void updateTitleAndMenus() { if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0) { repaint(); return; } setChainMenuItems(jmb.chainNames); jmb.colourBySequence(ap.av.getShowSequenceFeatures(), ap.av.alignment); this.setTitle(jmb.getViewerTitle()); } public void setJalviewColourScheme(ColourSchemeI ucs) { jmb.setJalviewColourScheme(ucs); } }