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 StructureListener,
45 JmolStatusListener, Runnable, SequenceStructureBinding
52 ScriptWindow scriptWindow;
60 StructureSelectionManager ssm;
64 RenderPanel renderPanel;
68 String fileLoadingError;
70 boolean colourBySequence = true;
72 boolean loadingFromArchive = false;
74 Vector atomsPicked = new Vector();
76 public AppJmol(String file, String id, SequenceI[] seq,
77 AlignmentPanel ap, String loadStatus, Rectangle bounds)
79 this(file, id, seq, ap, loadStatus, bounds, null);
82 public AppJmol(String file, String id, SequenceI[] seq,
83 AlignmentPanel ap, String loadStatus, Rectangle bounds,
86 loadingFromArchive = true;
87 pdbentry = new PDBEntry();
88 pdbentry.setFile(file);
92 this.setBounds(bounds);
93 colourBySequence = false;
94 seqColour.setSelected(false);
96 // jalview.gui.Desktop.addInternalFrame(this, "Loading File",
97 // bounds.width,bounds.height);
101 this.addInternalFrameListener(new InternalFrameAdapter()
103 public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
110 public synchronized void addSequence(SequenceI[] seq)
112 Vector v = new Vector();
113 for (int i = 0; i < sequence.length; i++)
114 v.addElement(sequence[i]);
116 for (int i = 0; i < seq.length; i++)
117 if (!v.contains(seq[i]))
118 v.addElement(seq[i]);
120 SequenceI[] tmp = new SequenceI[v.size()];
125 public AppJmol(PDBEntry pdbentry, SequenceI[] seq, String[] chains,
128 // ////////////////////////////////
129 // Is the pdb file already loaded?
130 String alreadyMapped = StructureSelectionManager
131 .getStructureSelectionManager().alreadyMappedToFile(
134 if (alreadyMapped != null)
136 int option = JOptionPane
137 .showInternalConfirmDialog(
140 + " is already displayed."
141 + "\nDo you want to map sequences to the visible structure?",
142 "Map Sequences to Visible Window: "
143 + pdbentry.getId(), JOptionPane.YES_NO_OPTION);
145 if (option == JOptionPane.YES_OPTION)
147 StructureSelectionManager.getStructureSelectionManager()
148 .setMapping(seq, chains, alreadyMapped,
149 AppletFormatAdapter.FILE);
150 if (ap.seqPanel.seqCanvas.fr != null)
152 ap.seqPanel.seqCanvas.fr.featuresAdded();
153 ap.paintAlignment(true);
156 // Now this AppJmol is mapped to new sequences. We must add them to
157 // the exisiting array
158 JInternalFrame[] frames = Desktop.instance.getAllFrames();
160 for (int i = 0; i < frames.length; i++)
162 if (frames[i] instanceof AppJmol)
164 AppJmol topJmol = ((AppJmol) frames[i]);
165 if (topJmol.pdbentry.getFile().equals(alreadyMapped))
167 topJmol.addSequence(seq);
176 // /////////////////////////////////
179 this.pdbentry = pdbentry;
181 this.setSize(400, 400);
182 // jalview.gui.Desktop.addInternalFrame(this, "Jmol
183 // View"+(pdbentry.getId()!=null ? "for "+pdbentry.getId()
186 if (pdbentry.getFile() != null)
188 initJmol("load \"" + pdbentry.getFile() + "\"");
192 Thread worker = new Thread(this);
196 this.addInternalFrameListener(new InternalFrameAdapter()
198 public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
205 void initJmol(String command)
207 renderPanel = new RenderPanel();
209 this.getContentPane().add(renderPanel, java.awt.BorderLayout.CENTER);
211 StringBuffer title = new StringBuffer(sequence[0].getName() + ":"
214 if (pdbentry.getProperty() != null)
216 if (pdbentry.getProperty().get("method") != null)
218 title.append(" Method: ");
219 title.append(pdbentry.getProperty().get("method"));
221 if (pdbentry.getProperty().get("chains") != null)
223 title.append(" Chain:");
224 title.append(pdbentry.getProperty().get("chains"));
228 this.setTitle(title.toString());
229 jalview.gui.Desktop.addInternalFrame(this, title.toString(),
230 getBounds().width, getBounds().height);
231 // * OK, but safer to assign htmlName, URL bases, comandOptions, and
232 // statusListener now.
234 viewer = org.jmol.api.JmolViewer.allocateViewer(renderPanel,
235 new SmarterJmolAdapter(), "", null, null, "", this);
237 jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
239 viewer.evalStringQuiet(command);
242 void setChainMenuItems(Vector chains)
244 chainMenu.removeAll();
246 JMenuItem menuItem = new JMenuItem("All");
247 menuItem.addActionListener(new ActionListener()
249 public void actionPerformed(ActionEvent evt)
251 allChainsSelected = true;
252 for (int i = 0; i < chainMenu.getItemCount(); i++)
254 if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
255 ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
258 allChainsSelected = false;
262 chainMenu.add(menuItem);
264 for (int c = 0; c < chains.size(); c++)
266 menuItem = new JCheckBoxMenuItem(chains.elementAt(c).toString(), true);
267 menuItem.addItemListener(new ItemListener()
269 public void itemStateChanged(ItemEvent evt)
271 if (!allChainsSelected)
276 chainMenu.add(menuItem);
280 boolean allChainsSelected = false;
285 StringBuffer cmd = new StringBuffer();
288 for (int i = 0; i < chainMenu.getItemCount(); i++)
290 if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
292 JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
293 if (item.isSelected())
294 { lbl = item.getText();
299 mlength = lbl.indexOf(":", p);
300 } while (p < mlength && mlength < (lbl.length() - 2));
301 if (pdbentry.getId().equals(lbl.substring(0,mlength)))
303 mnum = 1+getModelNum(pdbentry.getFile());
305 {cmd.append(":" + lbl.substring(mlength + 1) + " /"
313 if (cmd.length() > 0)
314 cmd.setLength(cmd.length() - 4);
316 viewer.evalStringQuiet("select *;restrict " + cmd + ";cartoon;center "
320 private int getModelNum(String modelFileName)
322 String[] mfn = getPdbFile();
327 for (int i = 0; i < mfn.length; i++)
329 if (mfn[i].equalsIgnoreCase(modelFileName))
337 viewer.setModeMouse(org.jmol.viewer.JmolConstants.MOUSE_NONE);
338 // remove listeners for all structures in viewer
339 StructureSelectionManager.getStructureSelectionManager()
340 .removeStructureViewerListener(this, getPdbFile());
341 // and shut down jmol
342 viewer.evalStringQuiet("zap");
343 viewer.setJmolStatusListener(null);
351 // TODO: replace with reference fetching/transfer code (validate PDBentry
353 jalview.ws.dbsources.Pdb pdbclient = new jalview.ws.dbsources.Pdb();
355 if ((pdbseq = pdbclient.getSequenceRecords(pdbentry.getId())) != null)
357 // just transfer the file name from the first seuqence's first PDBEntry
358 pdbentry.setFile(((PDBEntry) pdbseq.getSequenceAt(0).getPDBId()
359 .elementAt(0)).getFile());
360 initJmol("load " + pdbentry.getFile());
365 .showInternalMessageDialog(
368 + " could not be retrieved. Please try downloading the file manually.",
369 "Couldn't load file", JOptionPane.ERROR_MESSAGE);
372 } catch (OutOfMemoryError oomerror)
374 new OOMWarning("Retrieving PDB id " + pdbentry.getId() + " from MSD",
376 } catch (Exception ex)
378 ex.printStackTrace();
382 public void pdbFile_actionPerformed(ActionEvent actionEvent)
384 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
385 .getProperty("LAST_DIRECTORY"));
387 chooser.setFileView(new JalviewFileView());
388 chooser.setDialogTitle("Save PDB File");
389 chooser.setToolTipText("Save");
391 int value = chooser.showSaveDialog(this);
393 if (value == JalviewFileChooser.APPROVE_OPTION)
397 BufferedReader in = new BufferedReader(new FileReader(pdbentry
399 File outFile = chooser.getSelectedFile();
401 PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
403 while ((data = in.readLine()) != null)
405 if (!(data.indexOf("<PRE>") > -1 || data.indexOf("</PRE>") > -1))
411 } catch (Exception ex)
413 ex.printStackTrace();
418 public void viewMapping_actionPerformed(ActionEvent actionEvent)
420 jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
421 jalview.gui.Desktop.addInternalFrame(cap, "PDB - Sequence Mapping",
423 cap.setText(StructureSelectionManager.getStructureSelectionManager()
424 .printMapping(pdbentry.getFile()));
433 public void eps_actionPerformed(ActionEvent e)
435 makePDBImage(jalview.util.ImageMaker.EPS);
444 public void png_actionPerformed(ActionEvent e)
446 makePDBImage(jalview.util.ImageMaker.PNG);
449 void makePDBImage(int type)
451 int width = getWidth();
452 int height = getHeight();
454 jalview.util.ImageMaker im;
456 if (type == jalview.util.ImageMaker.PNG)
458 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG,
459 "Make PNG image from view", width, height, null, null);
463 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS,
464 "Make EPS file from view", width, height, null, this
468 if (im.getGraphics() != null)
470 Rectangle rect = new Rectangle(width, height);
471 viewer.renderScreenImage(im.getGraphics(), rect.getSize(), rect);
476 public void seqColour_actionPerformed(ActionEvent actionEvent)
479 colourBySequence = seqColour.isSelected();
480 colourBySequence(ap.alignFrame.alignPanel);
483 public void chainColour_actionPerformed(ActionEvent actionEvent)
485 colourBySequence = false;
486 seqColour.setSelected(false);
488 viewer.evalStringQuiet("select *;color chain");
492 public void chargeColour_actionPerformed(ActionEvent actionEvent)
494 colourBySequence = false;
495 seqColour.setSelected(false);
497 viewer.evalStringQuiet("select *;color white;select ASP,GLU;color red;"
498 + "select LYS,ARG;color blue;select CYS;color yellow");
502 public void zappoColour_actionPerformed(ActionEvent actionEvent)
504 setJalviewColourScheme(new ZappoColourScheme());
507 public void taylorColour_actionPerformed(ActionEvent actionEvent)
509 setJalviewColourScheme(new TaylorColourScheme());
512 public void hydroColour_actionPerformed(ActionEvent actionEvent)
514 setJalviewColourScheme(new HydrophobicColourScheme());
517 public void helixColour_actionPerformed(ActionEvent actionEvent)
519 setJalviewColourScheme(new HelixColourScheme());
522 public void strandColour_actionPerformed(ActionEvent actionEvent)
524 setJalviewColourScheme(new StrandColourScheme());
527 public void turnColour_actionPerformed(ActionEvent actionEvent)
529 setJalviewColourScheme(new TurnColourScheme());
532 public void buriedColour_actionPerformed(ActionEvent actionEvent)
534 setJalviewColourScheme(new BuriedColourScheme());
537 public void setJalviewColourScheme(ColourSchemeI cs)
540 colourBySequence = false;
541 seqColour.setSelected(false);
550 Enumeration en = ResidueProperties.aa3Hash.keys();
551 StringBuffer command = new StringBuffer("select *;color white;");
552 while (en.hasMoreElements())
554 res = en.nextElement().toString();
555 index = ((Integer) ResidueProperties.aa3Hash.get(res)).intValue();
559 col = cs.findColour(ResidueProperties.aa[index].charAt(0));
561 command.append("select " + res + ";color[" + col.getRed() + ","
562 + col.getGreen() + "," + col.getBlue() + "];");
565 viewer.evalStringQuiet(command.toString());
569 public void userColour_actionPerformed(ActionEvent actionEvent)
571 new UserDefinedColours(this, null);
574 public void backGround_actionPerformed(ActionEvent actionEvent)
576 java.awt.Color col = JColorChooser.showDialog(this,
577 "Select Background Colour", null);
582 viewer.evalStringQuiet("background [" + col.getRed() + ","
583 + col.getGreen() + "," + col.getBlue() + "];");
587 private void jmolHistory(boolean enable)
589 viewer.setBooleanProperty("history", enable);
592 public void jmolHelp_actionPerformed(ActionEvent actionEvent)
596 jalview.util.BrowserLauncher
597 .openURL("http://jmol.sourceforge.net/docs/JmolUserGuide/");
598 } catch (Exception ex)
602 String[] modelFileNames = null;
604 // ////////////////////////////////
605 // /StructureListener
606 public String[] getPdbFile()
608 if (modelFileNames == null)
610 String mset[] = new String[viewer.getModelCount()];
611 for (int i = 0; i < mset.length; i++)
614 String mname = viewer.getModelFileName(i);
617 System.err.println("Model "+i+" has no filename!");
620 File fpath = new File(mname);
621 mset[i] = fpath.toString();
622 } catch (Exception e)
624 System.err.println("Couldn't parse "+viewer.getModelFileName(i)+" as a file!");
627 modelFileNames = mset;
629 return modelFileNames;
632 Pattern pattern = Pattern
633 .compile("\\[(.*)\\]([0-9]+)(:[a-zA-Z]*)?\\.([a-zA-Z]+).*(/[0-9]*)?");
637 public void mouseOverStructure(int atomIndex, String strInfo)
639 // copied from AppJmol - will be refactored to binding eventually
641 int mdlSep = strInfo.indexOf("/");
642 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
644 if (chainSeparator == -1)
646 chainSeparator = strInfo.indexOf(".");
647 if (mdlSep > -1 && mdlSep < chainSeparator)
649 chainSeparator1 = chainSeparator;
650 chainSeparator = mdlSep;
653 pdbResNum = Integer.parseInt(strInfo.substring(
654 strInfo.indexOf("]") + 1, chainSeparator));
658 if (strInfo.indexOf(":") > -1)
659 chainId = strInfo.substring(strInfo.indexOf(":") + 1, strInfo
666 String pdbfilename = pdbentry.getFile();
669 if (chainSeparator1 == -1)
671 chainSeparator1 = strInfo.indexOf(".", mdlSep);
673 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
674 chainSeparator1) : strInfo.substring(mdlSep + 1);
677 // recover PDB filename for the model hovered over.
679 .getModelFileName(new Integer(mdlId).intValue() - 1);
680 } catch (Exception e)
685 if (lastMessage == null || !lastMessage.equals(strInfo))
686 ssm.mouseOverStructure(pdbResNum, chainId, pdbfilename);
688 lastMessage = strInfo;
690 * Old Implementation based on Pattern regex.
691 Matcher matcher = pattern.matcher(strInfo);
694 int pdbResNum = Integer.parseInt(matcher.group(2));
695 String chainId = matcher.group(3);
698 chainId = chainId.substring(1, chainId.length());
703 String mdlId = matcher.group(4);
704 String pdbfilename = pdbentry.getFile();
706 if (mdlId!=null && mdlId.length()>0)
709 // recover PDB filename for the model hovered over.
710 pdbfilename = viewer.getModelFileName(new Integer(mdlId).intValue()-1);
711 } catch (Exception e) {};
713 if (lastMessage == null || !lastMessage.equals(strInfo))
715 ssm.mouseOverStructure(pdbResNum, chainId, pdbfilename);
717 lastMessage = strInfo; */
720 StringBuffer resetLastRes = new StringBuffer();
722 StringBuffer eval = new StringBuffer();
724 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
727 int mdlNum = 1+getModelNum(pdbfile);
734 // if (!pdbfile.equals(pdbentry.getFile()))
736 if (resetLastRes.length() > 0)
738 viewer.evalStringQuiet(resetLastRes.toString());
742 eval.append("select " + pdbResNum); // +modelNum
744 resetLastRes.setLength(0);
745 resetLastRes.append("select " + pdbResNum); // +modelNum
747 if (!chain.equals(" "))
750 resetLastRes.append(":");
752 resetLastRes.append(chain);
756 eval.append(" /" + (mdlNum));
757 resetLastRes.append(" /" + (mdlNum));
759 eval.append(";wireframe 100;" + eval.toString() + " and not hetero;");
761 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
762 + " and not hetero; spacefill 0;");
764 eval.append("spacefill 200;select none");
766 viewer.evalStringQuiet(eval.toString());
770 public Color getColour(int atomIndex, int pdbResNum, String chain,
773 if (!pdbfile.equals(pdbentry.getFile()))
776 return new Color(viewer.getAtomArgb(atomIndex));
779 public void updateColours(Object source)
781 colourBySequence((AlignmentPanel) source);
784 // End StructureListener
785 // //////////////////////////
789 FeatureRenderer fr = null;
791 public void colourBySequence(AlignmentPanel sourceap)
795 if (!colourBySequence || ap.alignFrame.getCurrentView() != ap.av)
798 String[] files = getPdbFile();
800 SequenceRenderer sr = new SequenceRenderer(ap.av);
802 boolean showFeatures = false;
804 if (ap.av.showSequenceFeatures)
809 fr = new jalview.gui.FeatureRenderer(ap);
812 fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer());
815 StringBuffer command = new StringBuffer();
816 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
818 StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
820 if (mapping == null || mapping.length < 1)
825 for (int sp, s = 0; s < sequence.length; s++)
827 for (int m = 0; m < mapping.length; m++)
829 if (mapping[m].getSequence() == sequence[s]
830 && (sp = ap.av.alignment.findIndex(sequence[s])) > -1)
832 SequenceI asp = ap.av.alignment.getSequenceAt(sp);
833 for (int r = 0; r < asp.getLength(); r++)
835 // No mapping to gaps in sequence.
836 if (jalview.util.Comparison.isGap(asp.getCharAt(r)))
840 int pos = mapping[m].getPDBResNum(asp.findPosition(r));
842 if (pos < 1 || pos == lastPos)
847 Color col = sr.getResidueBoxColour(asp, r);
850 col = fr.findFeatureColour(col, asp, r);
851 String newSelcom = (mapping[m].getChain() != " " ? ":"
852 + mapping[m].getChain() : "")
861 + col.getBlue() + "]";
862 if (command.toString().endsWith(newSelcom))
864 command = condenseCommand(command, pos);
868 command.append(";select " + pos);
869 command.append(newSelcom);
878 if (lastCommand == null || !lastCommand.equals(command.toString()))
880 viewer.evalStringQuiet(command.toString());
883 lastCommand = command.toString();
886 StringBuffer condenseCommand(StringBuffer command, int pos)
888 StringBuffer sb = new StringBuffer(command.substring(0, command
889 .lastIndexOf("select") + 7));
891 command.delete(0, sb.length());
895 if (command.indexOf("-") > -1)
897 start = command.substring(0, command.indexOf("-"));
901 start = command.substring(0, command.indexOf(":"));
904 sb.append(start + "-" + pos + command.substring(command.indexOf(":")));
909 // ///////////////////////////////
910 // JmolStatusListener
912 public String eval(String strEval)
914 // System.out.println(strEval);
915 // "# 'eval' is implemented only for the applet.";
919 public void createImage(String file, String type, int quality)
921 System.out.println("JMOL CREATE IMAGE");
924 public void notifyFileLoaded(String fullPathName, String fileName2,
925 String modelName, String errorMsg, int modelParts)
927 if (errorMsg != null)
929 fileLoadingError = errorMsg;
934 fileLoadingError = null;
935 modelFileNames = null;
937 String[] modelfilenames = getPdbFile();
938 ssm = StructureSelectionManager.getStructureSelectionManager();
939 boolean modelsloaded=false;
940 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
942 String fileName = modelfilenames[modelnum];
944 if (fileName != null)
947 // search pdbentries and sequences to find correct pdbentry and sequence[] pair for this filename
948 if (pdbentry.getFile().equals(fileName))
950 // TODO: do some checking using the modelPts number of parts against our
951 // own estimate of the number of chains
953 MCview.PDBfile pdbFile = ssm.setMapping(sequence, chains, pdbentry
954 .getFile(), AppletFormatAdapter.FILE);
955 Vector chains = new Vector();
956 for (int i = 0; i < pdbFile.chains.size(); i++)
959 .addElement(new String(pdbFile.id+":"+((MCview.PDBChain) pdbFile.chains.elementAt(i)).id));
961 setChainMenuItems(chains);
963 if (!loadingFromArchive)
966 .evalStringQuiet("model 0; select backbone;restrict;cartoon;wireframe off;spacefill off");
968 colourBySequence(ap);
973 loadingFromArchive = false;
976 // this is a foreign pdb file that jalview doesn't know about - add it to the dataset
977 // and try to find a home - either on a matching sequence or as a new sequence.
978 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
980 // parse pdb file into a chain, etc.
981 // locate best match for pdb in associated views and add mapping to
989 ssm.addStructureViewerListener(this);
990 jmolpopup.updateComputedMenus();
994 public void sendConsoleEcho(String strEcho)
996 if (scriptWindow != null)
997 scriptWindow.sendConsoleEcho(strEcho);
1000 public void sendConsoleMessage(String strStatus)
1002 if (scriptWindow != null)
1003 scriptWindow.sendConsoleMessage(strStatus);
1006 public void notifyScriptTermination(String strStatus, int msWalltime)
1008 if (scriptWindow != null)
1009 scriptWindow.notifyScriptTermination(strStatus, msWalltime);
1012 public void handlePopupMenu(int x, int y)
1014 jmolpopup.show(x, y);
1017 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1019 notifyAtomPicked(iatom, strMeasure, null);
1022 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
1024 if (strData != null)
1026 Cache.log.info("Non null pick data string: " + strData
1027 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
1030 Matcher matcher = pattern.matcher(strInfo);
1034 String resnum = new String(matcher.group(2));
1035 String chainId = matcher.group(3);
1037 String picked = resnum;
1040 if (chainId != null)
1041 picked += (":" + chainId.substring(1, chainId.length()));
1043 int chainSeparator = strInfo.indexOf(":");
1045 if (chainSeparator == -1)
1046 chainSeparator = strInfo.indexOf(".");
1048 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
1050 String mdlString="";
1051 if ((p=strInfo.indexOf(":")) > -1)
1052 picked += strInfo.substring(p + 1, strInfo
1055 if ((p=strInfo.indexOf("/"))> -1)
1057 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
1059 picked = "((" + picked + ".CA" + mdlString+")|(" + picked + ".P" + mdlString+"))";
1061 if (!atomsPicked.contains(picked))
1063 // TODO: re-instate chain ID separator dependent labelling for both applet and application
1064 // if (chainId != null)
1065 viewer.evalString("select " + picked + ";label %n %r:%c");
1067 // viewer.evalString("select " + picked + ";label %n %r");
1068 atomsPicked.addElement(picked);
1072 viewer.evalString("select " + picked + ";label off");
1073 atomsPicked.removeElement(picked);
1076 if (scriptWindow != null)
1078 scriptWindow.sendConsoleMessage(strInfo);
1079 scriptWindow.sendConsoleMessage("\n");
1083 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
1087 Cache.log.info("Non null hover data string: " + data
1088 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
1090 mouseOverStructure(atomIndex, strInfo);
1094 public void showUrl(String url)
1098 jalview.util.BrowserLauncher.openURL(url);
1099 } catch (IOException e)
1101 Cache.log.error("Failed to launch Jmol-associated url " + url, e);
1102 // TODO: 2.6 : warn user if browser was not configured.
1106 public void showConsole(boolean showConsole)
1108 if (scriptWindow == null)
1109 scriptWindow = new ScriptWindow(this);
1113 if (splitPane == null)
1115 splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
1116 splitPane.setTopComponent(renderPanel);
1117 splitPane.setBottomComponent(scriptWindow);
1118 this.getContentPane().add(splitPane, BorderLayout.CENTER);
1121 splitPane.setDividerLocation(getHeight() - 200);
1122 splitPane.validate();
1126 if (splitPane != null)
1127 splitPane.setVisible(false);
1131 this.getContentPane().add(renderPanel, BorderLayout.CENTER);
1137 public float[][] functionXY(String functionName, int x, int y)
1142 // /End JmolStatusListener
1143 // /////////////////////////////
1145 class RenderPanel extends JPanel
1147 final Dimension currentSize = new Dimension();
1149 final Rectangle rectClip = new Rectangle();
1151 public void paintComponent(Graphics g)
1153 getSize(currentSize);
1154 g.getClipBounds(rectClip);
1158 g.setColor(Color.black);
1159 g.fillRect(0, 0, currentSize.width, currentSize.height);
1160 g.setColor(Color.white);
1161 g.setFont(new Font("Verdana", Font.BOLD, 14));
1162 g.drawString("Retrieving PDB data....", 20, currentSize.height / 2);
1164 else if (fileLoadingError != null)
1166 g.setColor(Color.black);
1167 g.fillRect(0, 0, currentSize.width, currentSize.height);
1168 g.setColor(Color.white);
1169 g.setFont(new Font("Verdana", Font.BOLD, 14));
1170 g.drawString("Error loading file..." + pdbentry.getId(), 20,
1171 currentSize.height / 2);
1175 viewer.renderScreenImage(g, currentSize, rectClip);
1180 String viewId = null;
1182 public String getViewId()
1186 viewId = System.currentTimeMillis() + "." + this.hashCode();
1192 public String createImage(String fileName, String type,
1193 Object textOrBytes, int quality)
1195 // TODO Auto-generated method stub
1200 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
1202 // TODO Auto-generated method stub
1207 public Hashtable getRegistryInfo()
1209 // TODO Auto-generated method stub
1214 public void notifyCallback(int type, Object[] data)
1220 case JmolConstants.CALLBACK_LOADSTRUCT:
1221 notifyFileLoaded((String) data[1], (String) data[2],
1222 (String) data[3], (String) data[4], ((Integer) data[5])
1226 case JmolConstants.CALLBACK_PICK:
1227 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
1229 // also highlight in alignment
1230 case JmolConstants.CALLBACK_HOVER:
1231 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
1234 case JmolConstants.CALLBACK_SCRIPT:
1235 notifyScriptTermination((String) data[2], ((Integer) data[3])
1238 case JmolConstants.CALLBACK_ECHO:
1239 sendConsoleEcho((String) data[1]);
1241 case JmolConstants.CALLBACK_MESSAGE:
1242 sendConsoleMessage((data == null) ? ((String) null)
1243 : (String) data[1]);
1245 case JmolConstants.CALLBACK_MEASURE:
1246 case JmolConstants.CALLBACK_CLICK:
1248 System.err.println("Unhandled callback " + type + " " + data);
1251 } catch (Exception e)
1253 Cache.log.warn("Squashed Jmol callback handler error: ", e);
1258 public boolean notifyEnabled(int callbackPick)
1260 switch (callbackPick)
1262 case JmolConstants.CALLBACK_ECHO:
1263 case JmolConstants.CALLBACK_LOADSTRUCT:
1264 case JmolConstants.CALLBACK_MEASURE:
1265 case JmolConstants.CALLBACK_MESSAGE:
1266 case JmolConstants.CALLBACK_PICK:
1267 case JmolConstants.CALLBACK_SCRIPT:
1268 case JmolConstants.CALLBACK_HOVER:
1269 case JmolConstants.CALLBACK_ERROR:
1271 case JmolConstants.CALLBACK_CLICK:
1272 case JmolConstants.CALLBACK_ANIMFRAME:
1273 case JmolConstants.CALLBACK_MINIMIZATION:
1274 case JmolConstants.CALLBACK_RESIZE:
1275 case JmolConstants.CALLBACK_SYNC:
1281 public void setCallbackFunction(String callbackType,
1282 String callbackFunction)
1284 Cache.log.debug("Ignoring set-callback request to associate "
1285 + callbackType + " with function " + callbackFunction);