2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
3 * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
20 import java.util.regex.*;
24 import javax.swing.event.*;
25 import java.awt.event.*;
28 import jalview.jbgui.GStructureViewer;
29 import jalview.api.SequenceStructureBinding;
30 import jalview.bin.Cache;
31 import jalview.datamodel.*;
33 import jalview.structure.*;
34 import jalview.datamodel.PDBEntry;
36 import jalview.schemes.*;
37 import jalview.ws.ebi.EBIFetchClient;
39 import org.jmol.api.*;
40 import org.jmol.adapter.smarter.SmarterJmolAdapter;
41 import org.jmol.popup.*;
42 import org.jmol.viewer.JmolConstants;
44 public class AppJmol extends GStructureViewer implements Runnable,
45 SequenceStructureBinding
50 ScriptWindow scriptWindow;
54 RenderPanel renderPanel;
58 Vector atomsPicked = new Vector();
60 public AppJmol(String file, String id, SequenceI[] seq,
61 AlignmentPanel ap, String loadStatus, Rectangle bounds)
63 this(file, id, seq, ap, loadStatus, bounds, null);
66 public AppJmol(String file, String id, SequenceI[] seq,
67 AlignmentPanel ap, String loadStatus, Rectangle bounds,
70 PDBEntry pdbentry = new PDBEntry();
71 pdbentry.setFile(file);
73 // / TODO: check if protocol is needed to be set, and if chains are
75 jmb = new AppJmolBinding(this, new PDBEntry[]
76 { pdbentry }, seq, null, null);
78 jmb.setLoadingFromArchive(true);
80 this.setBounds(bounds);
81 jmb.setColourBySequence(false);
82 seqColour.setSelected(false);
84 // jalview.gui.Desktop.addInternalFrame(this, "Loading File",
85 // bounds.width,bounds.height);
87 this.addInternalFrameListener(new InternalFrameAdapter()
89 public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
94 initJmol(loadStatus); // pdbentry, seq, JBPCHECK!
98 public AppJmol(PDBEntry pdbentry, SequenceI[] seq, String[] chains,
101 // ////////////////////////////////
102 // Is the pdb file already loaded?
103 String alreadyMapped = StructureSelectionManager
104 .getStructureSelectionManager().alreadyMappedToFile(
107 if (alreadyMapped != null)
109 int option = JOptionPane
110 .showInternalConfirmDialog(
113 + " is already displayed."
114 + "\nDo you want to re-use this viewer ?",
115 "Map Sequences to Visible Window: "
116 + pdbentry.getId(), JOptionPane.YES_NO_OPTION);
118 if (option == JOptionPane.YES_OPTION)
120 StructureSelectionManager.getStructureSelectionManager()
121 .setMapping(seq, chains, alreadyMapped,
122 AppletFormatAdapter.FILE);
123 if (ap.seqPanel.seqCanvas.fr != null)
125 ap.seqPanel.seqCanvas.fr.featuresAdded();
126 ap.paintAlignment(true);
129 // Now this AppJmol is mapped to new sequences. We must add them to
130 // the exisiting array
131 JInternalFrame[] frames = Desktop.instance.getAllFrames();
133 for (int i = 0; i < frames.length; i++)
135 if (frames[i] instanceof AppJmol)
137 AppJmol topJmol = ((AppJmol) frames[i]);
138 // JBPNOTE: this looks like a binding routine, rather than a gui
140 for (int pe = 0; pe < topJmol.jmb.pdbentry.length; pe++)
142 if (topJmol.jmb.pdbentry[pe].getFile().equals(alreadyMapped))
144 topJmol.jmb.addSequence(seq);
154 // /////////////////////////////////
156 jmb = new AppJmolBinding(this, new PDBEntry[]
157 { pdbentry }, seq, null, null);
159 setSize(400, 400); // probably should be a configurable/dynamic default here
161 if (pdbentry.getFile() != null)
163 initJmol("load \"" + pdbentry.getFile() + "\"");
167 Thread worker = new Thread(this);
171 this.addInternalFrameListener(new InternalFrameAdapter()
173 public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
181 void initJmol(String command)
183 jmb.setFinishedInit(false);
184 renderPanel = new RenderPanel();
185 // TODO: consider waiting until the structure/view is fully loaded before
187 this.getContentPane().add(renderPanel, java.awt.BorderLayout.CENTER);
188 jalview.gui.Desktop.addInternalFrame(this, jmb.getViewerTitle(),
189 getBounds().width, getBounds().height);
190 jmb.allocateViewer(renderPanel, "", null, null, "");
191 jmb.newJmolPopup(true, "Jmol", true);
192 jmb.evalStateCommand(command);
193 jmb.setFinishedInit(true);
196 void setChainMenuItems(Vector chains)
198 chainMenu.removeAll();
203 JMenuItem menuItem = new JMenuItem("All");
204 menuItem.addActionListener(new ActionListener()
206 public void actionPerformed(ActionEvent evt)
208 allChainsSelected = true;
209 for (int i = 0; i < chainMenu.getItemCount(); i++)
211 if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
212 ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
215 allChainsSelected = false;
219 chainMenu.add(menuItem);
221 for (int c = 0; c < chains.size(); c++)
223 menuItem = new JCheckBoxMenuItem(chains.elementAt(c).toString(), true);
224 menuItem.addItemListener(new ItemListener()
226 public void itemStateChanged(ItemEvent evt)
228 if (!allChainsSelected)
233 chainMenu.add(menuItem);
237 boolean allChainsSelected = false;
241 Vector toshow = new Vector();
243 int mlength, p, mnum;
244 for (int i = 0; i < chainMenu.getItemCount(); i++)
246 if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
248 JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
249 if (item.isSelected())
251 toshow.addElement(item.getText());
255 jmb.centerViewer(toshow);
261 // TODO: check for memory leaks where instance isn't finalised because jmb
262 // holds a reference to the window
269 // todo - record which pdbids were successfuly imported.
270 StringBuffer errormsgs = new StringBuffer(), files = new StringBuffer();
273 // TODO: replace with reference fetching/transfer code (validate PDBentry
275 jalview.ws.dbsources.Pdb pdbclient = new jalview.ws.dbsources.Pdb();
276 for (int pi = 0; pi < jmb.pdbentry.length; pi++)
279 if ((pdbseq = pdbclient.getSequenceRecords(pdbid = jmb.pdbentry[pi]
283 // just transfer the file name from the first sequence's first
285 jmb.pdbentry[pi].setFile(file = ((PDBEntry) pdbseq.getSequenceAt(
286 0).getPDBId().elementAt(0)).getFile());
287 files.append("\"" + file + "\"");
291 errormsgs.append("'" + pdbid + "' ");
294 } catch (OutOfMemoryError oomerror)
296 new OOMWarning("Retrieving PDB id " + pdbid, oomerror);
297 } catch (Exception ex)
299 ex.printStackTrace();
300 errormsgs.append("'" + pdbid + "'");
302 if (errormsgs.length() > 0)
305 JOptionPane.showInternalMessageDialog(Desktop.desktop,
306 "The following pdb entries could not be retrieved from the PDB:\n"
307 + errormsgs.toString()
308 + "\nPlease try downloading them manually.",
309 "Couldn't load file", JOptionPane.ERROR_MESSAGE);
312 if (files.length() > 0)
316 initJmol("load FILES " + files.toString());
317 } catch (OutOfMemoryError oomerror)
319 new OOMWarning("When trying to open the Jmol viewer!", oomerror);
320 Cache.log.debug("File locations are " + files);
321 } catch (Exception ex)
323 Cache.log.error("Couldn't open Jmol viewer!", ex);
328 public void pdbFile_actionPerformed(ActionEvent actionEvent)
330 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
331 .getProperty("LAST_DIRECTORY"));
333 chooser.setFileView(new JalviewFileView());
334 chooser.setDialogTitle("Save PDB File");
335 chooser.setToolTipText("Save");
337 int value = chooser.showSaveDialog(this);
339 if (value == JalviewFileChooser.APPROVE_OPTION)
343 // TODO: cope with multiple PDB files in view
344 BufferedReader in = new BufferedReader(new FileReader(jmb.getPdbFile()[0]));
345 File outFile = chooser.getSelectedFile();
347 PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
349 while ((data = in.readLine()) != null)
351 if (!(data.indexOf("<PRE>") > -1 || data.indexOf("</PRE>") > -1))
357 } catch (Exception ex)
359 ex.printStackTrace();
364 public void viewMapping_actionPerformed(ActionEvent actionEvent)
366 jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
367 try {for (int pdbe = 0; pdbe<jmb.pdbentry.length; pdbe++) {
368 cap.appendText(StructureSelectionManager.getStructureSelectionManager()
369 .printMapping(jmb.pdbentry[pdbe].getFile()));
370 cap.appendText("\n");
371 }} catch (OutOfMemoryError e)
373 new OOMWarning("composing sequence-structure alignments for display in text box.", e);
377 jalview.gui.Desktop.addInternalFrame(cap, "PDB - Sequence Mapping",
387 public void eps_actionPerformed(ActionEvent e)
389 makePDBImage(jalview.util.ImageMaker.EPS);
398 public void png_actionPerformed(ActionEvent e)
400 makePDBImage(jalview.util.ImageMaker.PNG);
403 void makePDBImage(int type)
405 int width = getWidth();
406 int height = getHeight();
408 jalview.util.ImageMaker im;
410 if (type == jalview.util.ImageMaker.PNG)
412 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG,
413 "Make PNG image from view", width, height, null, null);
417 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS,
418 "Make EPS file from view", width, height, null, this
422 if (im.getGraphics() != null)
424 Rectangle rect = new Rectangle(width, height);
425 jmb.viewer.renderScreenImage(im.getGraphics(), rect.getSize(), rect);
430 public void seqColour_actionPerformed(ActionEvent actionEvent)
432 jmb.setColourBySequence(seqColour.isSelected());
433 // Set the colour using the current view for the associated alignframe
434 jmb.colourBySequence(ap.alignFrame.viewport.showSequenceFeatures, ap.alignFrame.viewport.alignment);
437 public void chainColour_actionPerformed(ActionEvent actionEvent)
439 chainColour.setSelected(true);
443 public void chargeColour_actionPerformed(ActionEvent actionEvent)
445 chargeColour.setSelected(true);
446 jmb.colourByCharge();
449 public void zappoColour_actionPerformed(ActionEvent actionEvent)
451 zappoColour.setSelected(true);
452 jmb.setJalviewColourScheme(new ZappoColourScheme());
455 public void taylorColour_actionPerformed(ActionEvent actionEvent)
457 taylorColour.setSelected(true);
458 jmb.setJalviewColourScheme(new TaylorColourScheme());
461 public void hydroColour_actionPerformed(ActionEvent actionEvent)
463 hydroColour.setSelected(true);
464 jmb.setJalviewColourScheme(new HydrophobicColourScheme());
467 public void helixColour_actionPerformed(ActionEvent actionEvent)
469 helixColour.setSelected(true);
470 jmb.setJalviewColourScheme(new HelixColourScheme());
473 public void strandColour_actionPerformed(ActionEvent actionEvent)
475 strandColour.setSelected(true);
476 jmb.setJalviewColourScheme(new StrandColourScheme());
479 public void turnColour_actionPerformed(ActionEvent actionEvent)
481 turnColour.setSelected(true);
482 jmb.setJalviewColourScheme(new TurnColourScheme());
485 public void buriedColour_actionPerformed(ActionEvent actionEvent)
487 buriedColour.setSelected(true);
488 jmb.setJalviewColourScheme(new BuriedColourScheme());
492 public void userColour_actionPerformed(ActionEvent actionEvent)
494 userColour.setSelected(true);
495 new UserDefinedColours(this, null);
498 public void backGround_actionPerformed(ActionEvent actionEvent)
500 java.awt.Color col = JColorChooser.showDialog(this,
501 "Select Background Colour", null);
504 jmb.setBackgroundColour(col);
508 public void jmolHelp_actionPerformed(ActionEvent actionEvent)
512 jalview.util.BrowserLauncher
513 .openURL("http://jmol.sourceforge.net/docs/JmolUserGuide/");
514 } catch (Exception ex)
519 public void showConsole(boolean showConsole)
521 if (scriptWindow == null)
522 scriptWindow = new ScriptWindow(this);
526 if (splitPane == null)
528 splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
529 splitPane.setTopComponent(renderPanel);
530 splitPane.setBottomComponent(scriptWindow);
531 this.getContentPane().add(splitPane, BorderLayout.CENTER);
534 splitPane.setDividerLocation(getHeight() - 200);
535 splitPane.validate();
539 if (splitPane != null)
540 splitPane.setVisible(false);
544 this.getContentPane().add(renderPanel, BorderLayout.CENTER);
550 class RenderPanel extends JPanel
552 final Dimension currentSize = new Dimension();
554 final Rectangle rectClip = new Rectangle();
556 public void paintComponent(Graphics g)
558 getSize(currentSize);
559 g.getClipBounds(rectClip);
561 if (jmb.fileLoadingError != null)
563 g.setColor(Color.black);
564 g.fillRect(0, 0, currentSize.width, currentSize.height);
565 g.setColor(Color.white);
566 g.setFont(new Font("Verdana", Font.BOLD, 14));
567 g.drawString("Error loading file...", 20,
568 currentSize.height / 2);
569 StringBuffer sb = new StringBuffer();
571 for (int e=0;e<jmb.pdbentry.length; e++)
573 sb.append(jmb.pdbentry[e].getId());
574 if (e<jmb.pdbentry.length-1) {
578 if (e==jmb.pdbentry.length-1 || sb.length()>20)
581 g.drawString(sb.toString(), 20, currentSize.height/2 - lines*g.getFontMetrics().getHeight());
586 if (jmb == null || jmb.viewer == null || !jmb.isFinishedInit())
588 g.setColor(Color.black);
589 g.fillRect(0, 0, currentSize.width, currentSize.height);
590 g.setColor(Color.white);
591 g.setFont(new Font("Verdana", Font.BOLD, 14));
592 g.drawString("Retrieving PDB data....", 20, currentSize.height / 2);
596 jmb.viewer.renderScreenImage(g, currentSize, rectClip);
601 String viewId = null;
603 public String getViewId()
607 viewId = System.currentTimeMillis() + "." + this.hashCode();
611 public void updateTitleAndMenus()
613 if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0)
618 setChainMenuItems(jmb.chainNames);
619 jmb.colourBySequence(ap.av.getShowSequenceFeatures(), ap.av.alignment);
621 this.setTitle(jmb.getViewerTitle());
624 public void setJalviewColourScheme(ColourSchemeI ucs)
626 jmb.setJalviewColourScheme(ucs);