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 jalview.gui.Desktop.addInternalFrame(cap, "PDB - Sequence Mapping",
369 for (int pdbe = 0; pdbe<jmb.pdbentry.length; pdbe++) {
370 cap.appendText(StructureSelectionManager.getStructureSelectionManager()
371 .printMapping(jmb.pdbentry[pdbe].getFile()));
372 cap.appendText("\n");
382 public void eps_actionPerformed(ActionEvent e)
384 makePDBImage(jalview.util.ImageMaker.EPS);
393 public void png_actionPerformed(ActionEvent e)
395 makePDBImage(jalview.util.ImageMaker.PNG);
398 void makePDBImage(int type)
400 int width = getWidth();
401 int height = getHeight();
403 jalview.util.ImageMaker im;
405 if (type == jalview.util.ImageMaker.PNG)
407 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG,
408 "Make PNG image from view", width, height, null, null);
412 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS,
413 "Make EPS file from view", width, height, null, this
417 if (im.getGraphics() != null)
419 Rectangle rect = new Rectangle(width, height);
420 jmb.viewer.renderScreenImage(im.getGraphics(), rect.getSize(), rect);
425 public void seqColour_actionPerformed(ActionEvent actionEvent)
427 jmb.setColourBySequence(seqColour.isSelected());
428 // Set the colour using the current view for the associated alignframe
429 jmb.colourBySequence(ap.alignFrame.viewport.showSequenceFeatures, ap.alignFrame.viewport.alignment);
432 public void chainColour_actionPerformed(ActionEvent actionEvent)
434 chainColour.setSelected(true);
438 public void chargeColour_actionPerformed(ActionEvent actionEvent)
440 chargeColour.setSelected(true);
441 jmb.colourByCharge();
444 public void zappoColour_actionPerformed(ActionEvent actionEvent)
446 zappoColour.setSelected(true);
447 jmb.setJalviewColourScheme(new ZappoColourScheme());
450 public void taylorColour_actionPerformed(ActionEvent actionEvent)
452 taylorColour.setSelected(true);
453 jmb.setJalviewColourScheme(new TaylorColourScheme());
456 public void hydroColour_actionPerformed(ActionEvent actionEvent)
458 hydroColour.setSelected(true);
459 jmb.setJalviewColourScheme(new HydrophobicColourScheme());
462 public void helixColour_actionPerformed(ActionEvent actionEvent)
464 helixColour.setSelected(true);
465 jmb.setJalviewColourScheme(new HelixColourScheme());
468 public void strandColour_actionPerformed(ActionEvent actionEvent)
470 strandColour.setSelected(true);
471 jmb.setJalviewColourScheme(new StrandColourScheme());
474 public void turnColour_actionPerformed(ActionEvent actionEvent)
476 turnColour.setSelected(true);
477 jmb.setJalviewColourScheme(new TurnColourScheme());
480 public void buriedColour_actionPerformed(ActionEvent actionEvent)
482 buriedColour.setSelected(true);
483 jmb.setJalviewColourScheme(new BuriedColourScheme());
487 public void userColour_actionPerformed(ActionEvent actionEvent)
489 userColour.setSelected(true);
490 new UserDefinedColours(this, null);
493 public void backGround_actionPerformed(ActionEvent actionEvent)
495 java.awt.Color col = JColorChooser.showDialog(this,
496 "Select Background Colour", null);
499 jmb.setBackgroundColour(col);
503 public void jmolHelp_actionPerformed(ActionEvent actionEvent)
507 jalview.util.BrowserLauncher
508 .openURL("http://jmol.sourceforge.net/docs/JmolUserGuide/");
509 } catch (Exception ex)
514 public void showConsole(boolean showConsole)
516 if (scriptWindow == null)
517 scriptWindow = new ScriptWindow(this);
521 if (splitPane == null)
523 splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
524 splitPane.setTopComponent(renderPanel);
525 splitPane.setBottomComponent(scriptWindow);
526 this.getContentPane().add(splitPane, BorderLayout.CENTER);
529 splitPane.setDividerLocation(getHeight() - 200);
530 splitPane.validate();
534 if (splitPane != null)
535 splitPane.setVisible(false);
539 this.getContentPane().add(renderPanel, BorderLayout.CENTER);
545 class RenderPanel extends JPanel
547 final Dimension currentSize = new Dimension();
549 final Rectangle rectClip = new Rectangle();
551 public void paintComponent(Graphics g)
553 getSize(currentSize);
554 g.getClipBounds(rectClip);
556 if (jmb.fileLoadingError != null)
558 g.setColor(Color.black);
559 g.fillRect(0, 0, currentSize.width, currentSize.height);
560 g.setColor(Color.white);
561 g.setFont(new Font("Verdana", Font.BOLD, 14));
562 g.drawString("Error loading file...", 20,
563 currentSize.height / 2);
564 StringBuffer sb = new StringBuffer();
566 for (int e=0;e<jmb.pdbentry.length; e++)
568 sb.append(jmb.pdbentry[e].getId());
569 if (e<jmb.pdbentry.length-1) {
573 if (e==jmb.pdbentry.length-1 || sb.length()>20)
576 g.drawString(sb.toString(), 20, currentSize.height/2 - lines*g.getFontMetrics().getHeight());
581 if (jmb == null || jmb.viewer == null || !jmb.isFinishedInit())
583 g.setColor(Color.black);
584 g.fillRect(0, 0, currentSize.width, currentSize.height);
585 g.setColor(Color.white);
586 g.setFont(new Font("Verdana", Font.BOLD, 14));
587 g.drawString("Retrieving PDB data....", 20, currentSize.height / 2);
591 jmb.viewer.renderScreenImage(g, currentSize, rectClip);
596 String viewId = null;
598 public String getViewId()
602 viewId = System.currentTimeMillis() + "." + this.hashCode();
606 public void updateTitleAndMenus()
608 if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0)
613 setChainMenuItems(jmb.chainNames);
614 jmb.colourBySequence(ap.av.getShowSequenceFeatures(), ap.av.alignment);
616 this.setTitle(jmb.getViewerTitle());
619 public void setJalviewColourScheme(ColourSchemeI ucs)
621 jmb.setJalviewColourScheme(ucs);