2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
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
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.ext.jmol;
23 import jalview.api.FeatureRenderer;
24 import jalview.datamodel.AlignmentI;
25 import jalview.datamodel.HiddenColumns;
26 import jalview.datamodel.PDBEntry;
27 import jalview.datamodel.SequenceI;
28 import jalview.gui.IProgressIndicator;
29 import jalview.io.DataSourceType;
30 import jalview.io.StructureFile;
31 import jalview.structure.AtomSpec;
32 import jalview.structure.StructureSelectionManager;
33 import jalview.structures.models.AAStructureBindingModel;
34 import jalview.util.MessageManager;
36 import java.awt.Container;
37 import java.awt.event.ComponentEvent;
38 import java.awt.event.ComponentListener;
41 import java.util.ArrayList;
42 import java.util.BitSet;
43 import java.util.List;
45 import java.util.StringTokenizer;
46 import java.util.Vector;
48 import org.jmol.adapter.smarter.SmarterJmolAdapter;
49 import org.jmol.api.JmolAppConsoleInterface;
50 import org.jmol.api.JmolSelectionListener;
51 import org.jmol.api.JmolStatusListener;
52 import org.jmol.api.JmolViewer;
53 import org.jmol.c.CBK;
54 import org.jmol.viewer.Viewer;
56 public abstract class JalviewJmolBinding extends AAStructureBindingModel
57 implements JmolStatusListener, JmolSelectionListener,
60 private String lastMessage;
63 * when true, try to search the associated datamodel for sequences that are
64 * associated with any unknown structures in the Jmol view.
66 private boolean associateNewStructs = false;
68 private Vector<String> atomsPicked = new Vector<>();
70 private String lastCommand;
72 private boolean loadedInline;
74 private StringBuffer resetLastRes = new StringBuffer();
76 public Viewer jmolViewer;
78 public JalviewJmolBinding(StructureSelectionManager ssm,
79 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
80 DataSourceType protocol)
82 super(ssm, pdbentry, sequenceIs, protocol);
83 setStructureCommands(new JmolCommands());
85 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
86 * "jalviewJmol", ap.av.applet .getDocumentBase(),
87 * ap.av.applet.getCodeBase(), "", this);
89 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
93 public JalviewJmolBinding(StructureSelectionManager ssm,
94 SequenceI[][] seqs, Viewer theViewer)
98 jmolViewer = theViewer;
99 jmolViewer.setJmolStatusListener(this);
100 jmolViewer.addSelectionListener(this);
101 setStructureCommands(new JmolCommands());
105 * construct a title string for the viewer window based on the data jalview
110 public String getViewerTitle()
112 return getViewerTitle("Jmol", true);
115 public void closeViewer()
117 // remove listeners for all structures in viewer
118 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
119 jmolViewer.dispose();
122 releaseUIResources();
126 * superpose the structures associated with sequences in the alignment
127 * according to their corresponding positions.
129 * @deprecated not used - remove?
132 public void superposeStructures(AlignmentI alignment)
134 superposeStructures(alignment, -1, null);
138 * superpose the structures associated with sequences in the alignment
139 * according to their corresponding positions. ded)
141 * @param refStructure
142 * - select which pdb file to use as reference (default is -1 - the
143 * first structure in the alignment)
144 * @deprecated not used - remove?
147 public void superposeStructures(AlignmentI alignment, int refStructure)
149 superposeStructures(alignment, refStructure, null);
153 * superpose the structures associated with sequences in the alignment
154 * according to their corresponding positions. ded)
156 * @param refStructure
157 * - select which pdb file to use as reference (default is -1 - the
158 * first structure in the alignment)
161 * @deprecated not used - remove?
164 public void superposeStructures(AlignmentI alignment, int refStructure,
165 HiddenColumns hiddenCols)
167 superposeStructures(new AlignmentI[] { alignment },
169 { refStructure }, new HiddenColumns[] { hiddenCols });
176 public String superposeStructures(AlignmentI[] _alignment,
177 int[] _refStructure, HiddenColumns[] _hiddenCols)
179 while (jmolViewer.isScriptExecuting())
184 } catch (InterruptedException i)
190 * get the distinct structure files modelled
191 * (a file with multiple chains may map to multiple sequences)
193 String[] files = getStructureFiles();
194 if (!waitForFileLoad(files))
199 StringBuilder selectioncom = new StringBuilder(256);
200 // In principle - nSeconds specifies the speed of animation for each
201 // superposition - but is seems to behave weirdly, so we don't specify it.
202 String nSeconds = " ";
203 if (files.length > 10)
205 nSeconds = " 0.005 ";
209 nSeconds = " " + (2.0 / files.length) + " ";
210 // if (nSeconds).substring(0,5)+" ";
213 // see JAL-1345 - should really automatically turn off the animation for
214 // large numbers of structures, but Jmol doesn't seem to allow that.
216 // union of all aligned positions are collected together.
217 for (int a = 0; a < _alignment.length; a++)
219 int refStructure = _refStructure[a];
220 AlignmentI alignment = _alignment[a];
221 HiddenColumns hiddenCols = _hiddenCols[a];
222 if (a > 0 && selectioncom.length() > 0 && !selectioncom
223 .substring(selectioncom.length() - 1).equals("|"))
225 selectioncom.append("|");
227 // process this alignment
228 if (refStructure >= files.length)
231 "Invalid reference structure value " + refStructure);
236 * 'matched' bit j will be set for visible alignment columns j where
237 * all sequences have a residue with a mapping to the PDB structure
239 BitSet matched = new BitSet();
240 for (int m = 0; m < alignment.getWidth(); m++)
242 if (hiddenCols == null || hiddenCols.isVisible(m))
248 SuperposeData[] structures = new SuperposeData[files.length];
249 for (int f = 0; f < files.length; f++)
251 structures[f] = new SuperposeData(alignment.getWidth());
255 * Calculate the superposable alignment columns ('matched'), and the
256 * corresponding structure residue positions (structures.pdbResNo)
258 int candidateRefStructure = findSuperposableResidues(alignment,
259 matched, structures);
260 if (refStructure < 0)
263 * If no reference structure was specified, pick the first one that has
264 * a mapping in the alignment
266 refStructure = candidateRefStructure;
269 String[] selcom = new String[files.length];
270 int nmatched = matched.cardinality();
273 return (MessageManager.formatMessage("label.insufficient_residues",
278 * generate select statements to select regions to superimpose structures
281 // TODO extract method to construct selection statements
282 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
284 String chainCd = ":" + structures[pdbfnum].chain;
287 StringBuilder molsel = new StringBuilder();
290 int nextColumnMatch = matched.nextSetBit(0);
291 while (nextColumnMatch != -1)
293 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
294 if (lpos != pdbResNo - 1)
300 molsel.append(chainCd);
307 // continuous run - and lpos >-1
310 // at the beginning, so add dash
317 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
320 * add final selection phrase
325 molsel.append(chainCd);
328 if (molsel.length() > 1)
330 selcom[pdbfnum] = molsel.toString();
331 selectioncom.append("((");
332 selectioncom.append(selcom[pdbfnum].substring(1,
333 selcom[pdbfnum].length() - 1));
334 selectioncom.append(" )& ");
335 selectioncom.append(pdbfnum + 1);
336 selectioncom.append(".1)");
337 if (pdbfnum < files.length - 1)
339 selectioncom.append("|");
344 selcom[pdbfnum] = null;
348 StringBuilder command = new StringBuilder(256);
349 // command.append("set spinFps 10;\n");
351 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
353 if (pdbfnum == refStructure || selcom[pdbfnum] == null
354 || selcom[refStructure] == null)
358 command.append("echo ");
359 command.append("\"Superposing (");
360 command.append(structures[pdbfnum].pdbId);
361 command.append(") against reference (");
362 command.append(structures[refStructure].pdbId);
363 command.append(")\";\ncompare " + nSeconds);
365 command.append(Integer.toString(1 + pdbfnum));
366 command.append(".1} {");
367 command.append(Integer.toString(1 + refStructure));
368 // conformation=1 excludes alternate locations for CA (JAL-1757)
370 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
372 // for (int s = 0; s < 2; s++)
374 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
376 command.append(selcom[pdbfnum]);
377 command.append(selcom[refStructure]);
378 command.append(" ROTATE TRANSLATE;\n");
380 if (selectioncom.length() > 0)
382 // TODO is performing selectioncom redundant here? is done later on
383 // System.out.println("Select regions:\n" + selectioncom.toString());
384 executeCommand("select *; cartoons off; backbone; select ("
385 + selectioncom.toString() + "); cartoons; ", false);
386 // selcom.append("; ribbons; ");
387 String cmdString = command.toString();
388 // System.out.println("Superimpose command(s):\n" + cmdString);
390 executeCommand(cmdString, false);
393 if (selectioncom.length() > 0)
394 {// finally, mark all regions that were superposed.
395 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
397 selectioncom.setLength(selectioncom.length() - 1);
399 // System.out.println("Select regions:\n" + selectioncom.toString());
400 executeCommand("select *; cartoons off; backbone; select ("
401 + selectioncom.toString() + "); cartoons; ", false);
402 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
403 // cartoons; center "+selcom.toString());
410 public List<String> executeCommand(String command, boolean getReply)
417 if (lastCommand == null || !lastCommand.equals(command))
419 jmolViewer.evalStringQuiet(command + "\n");
422 lastCommand = command;
426 public void createImage(String file, String type, int quality)
428 System.out.println("JMOL CREATE IMAGE");
432 public String createImage(String fileName, String type,
433 Object textOrBytes, int quality)
435 System.out.println("JMOL CREATE IMAGE");
440 public String eval(String strEval)
442 // System.out.println(strEval);
443 // "# 'eval' is implemented only for the applet.";
447 // End StructureListener
448 // //////////////////////////
451 public float[][] functionXY(String functionName, int x, int y)
457 public float[][][] functionXYZ(String functionName, int nx, int ny,
460 // TODO Auto-generated method stub
465 * map between index of model filename returned from getPdbFile and the first
466 * index of models from this file in the viewer. Note - this is not trimmed -
467 * use getPdbFile to get number of unique models.
469 private int _modelFileNameMap[];
472 public synchronized String[] getStructureFiles()
474 List<String> mset = new ArrayList<>();
475 if (jmolViewer == null)
477 return new String[0];
480 if (modelFileNames == null)
482 int modelCount = jmolViewer.ms.mc;
483 String filePath = null;
484 for (int i = 0; i < modelCount; ++i)
486 filePath = jmolViewer.ms.getModelFileName(i);
487 if (!mset.contains(filePath))
492 modelFileNames = mset.toArray(new String[mset.size()]);
495 return modelFileNames;
499 * map from string to applet
502 public Map<String, Object> getRegistryInfo()
504 // TODO Auto-generated method stub
508 // ///////////////////////////////
509 // JmolStatusListener
511 public void handlePopupMenu(int x, int y)
513 // jmolpopup.show(x, y);
514 // jmolpopup.jpiShow(x, y);
518 * Highlight zero, one or more atoms on the structure
521 public void highlightAtoms(List<AtomSpec> atoms)
525 if (resetLastRes.length() > 0)
527 jmolViewer.evalStringQuiet(resetLastRes.toString());
528 resetLastRes.setLength(0);
530 for (AtomSpec atom : atoms)
532 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
533 atom.getChain(), atom.getPdbFile());
539 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
542 if (modelFileNames == null)
547 // look up file model number for this pdbfile
549 // may need to adjust for URLencoding here - we don't worry about that yet.
550 while (mdlNum < modelFileNames.length
551 && !pdbfile.equals(modelFileNames[mdlNum]))
555 if (mdlNum == modelFileNames.length)
562 StringBuilder cmd = new StringBuilder(64);
563 cmd.append("select ").append(String.valueOf(pdbResNum)); // +modelNum
565 resetLastRes.append("select ").append(String.valueOf(pdbResNum)); // +modelNum
568 resetLastRes.append(":");
569 if (!chain.equals(" "))
572 resetLastRes.append(chain);
575 cmd.append(" /").append(String.valueOf(mdlNum + 1));
576 resetLastRes.append("/").append(String.valueOf(mdlNum + 1));
578 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
580 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
581 + " and not hetero; spacefill 0;");
583 cmd.append("spacefill 200;select none");
585 jmolViewer.evalStringQuiet(cmd.toString());
590 private boolean debug = true;
592 private void jmolHistory(boolean enable)
594 jmolViewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
597 public void loadInline(String string)
601 // viewer.loadInline(strModel, isAppend);
603 // construct fake fullPathName and fileName so we can identify the file
605 // Then, construct pass a reader for the string to Jmol.
606 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
607 // fileName, null, reader, false, null, null, 0);
608 jmolViewer.openStringInline(string);
611 protected void mouseOverStructure(int atomIndex, final String strInfo)
614 int alocsep = strInfo.indexOf("^");
615 int mdlSep = strInfo.indexOf("/");
616 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
618 if (chainSeparator == -1)
620 chainSeparator = strInfo.indexOf(".");
621 if (mdlSep > -1 && mdlSep < chainSeparator)
623 chainSeparator1 = chainSeparator;
624 chainSeparator = mdlSep;
627 // handle insertion codes
630 pdbResNum = Integer.parseInt(
631 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
636 pdbResNum = Integer.parseInt(
637 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
641 if (strInfo.indexOf(":") > -1)
643 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
644 strInfo.indexOf("."));
651 String pdbfilename = modelFileNames[0]; // default is first model
654 if (chainSeparator1 == -1)
656 chainSeparator1 = strInfo.indexOf(".", mdlSep);
658 String mdlId = (chainSeparator1 > -1)
659 ? strInfo.substring(mdlSep + 1, chainSeparator1)
660 : strInfo.substring(mdlSep + 1);
663 // recover PDB filename for the model hovered over.
664 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
665 if (_modelFileNameMap != null)
667 int _mp = _modelFileNameMap.length - 1;
669 while (mnumber < _modelFileNameMap[_mp])
673 pdbfilename = modelFileNames[_mp];
677 if (mnumber >= 0 && mnumber < modelFileNames.length)
679 pdbfilename = modelFileNames[mnumber];
682 if (pdbfilename == null)
684 pdbfilename = new File(jmolViewer.ms.getModelFileName(mnumber))
688 } catch (Exception e)
694 * highlight position on alignment(s); if some text is returned,
695 * show this as a second line on the structure hover tooltip
697 String label = getSsm().mouseOverStructure(pdbResNum, chainId,
701 // change comma to pipe separator (newline token for Jmol)
702 label = label.replace(',', '|');
703 StringTokenizer toks = new StringTokenizer(strInfo, " ");
704 StringBuilder sb = new StringBuilder();
705 sb.append("select ").append(String.valueOf(pdbResNum)).append(":")
706 .append(chainId).append("/1");
707 sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
708 .append(toks.nextToken());
709 sb.append("|").append(label).append("\"");
710 executeCommand(sb.toString(), false);
714 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
716 if (strInfo.equals(lastMessage))
720 lastMessage = strInfo;
723 System.err.println("Ignoring additional hover info: " + data
724 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
726 mouseOverStructure(atomIndex, strInfo);
730 * { if (history != null && strStatus != null &&
731 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
735 public void notifyAtomPicked(int atomIndex, String strInfo,
739 * this implements the toggle label behaviour copied from the original
740 * structure viewer, MCView
744 System.err.println("Ignoring additional pick data string " + strData);
746 int chainSeparator = strInfo.indexOf(":");
748 if (chainSeparator == -1)
750 chainSeparator = strInfo.indexOf(".");
753 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
755 String mdlString = "";
756 if ((p = strInfo.indexOf(":")) > -1)
758 picked += strInfo.substring(p, strInfo.indexOf("."));
761 if ((p = strInfo.indexOf("/")) > -1)
763 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
765 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
769 if (!atomsPicked.contains(picked))
771 jmolViewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
772 atomsPicked.addElement(picked);
776 jmolViewer.evalString("select " + picked + ";label off");
777 atomsPicked.removeElement(picked);
780 // TODO: in application this happens
782 // if (scriptWindow != null)
784 // scriptWindow.sendConsoleMessage(strInfo);
785 // scriptWindow.sendConsoleMessage("\n");
791 public void notifyCallback(CBK type, Object[] data)
798 notifyFileLoaded((String) data[1], (String) data[2],
799 (String) data[3], (String) data[4],
800 ((Integer) data[5]).intValue());
804 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
806 // also highlight in alignment
807 // deliberate fall through
809 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
813 notifyScriptTermination((String) data[2],
814 ((Integer) data[3]).intValue());
817 sendConsoleEcho((String) data[1]);
821 (data == null) ? ((String) null) : (String) data[1]);
824 // System.err.println("Ignoring error callback.");
835 "Unhandled callback " + type + " " + data[1].toString());
838 } catch (Exception e)
840 System.err.println("Squashed Jmol callback handler error:");
846 public boolean notifyEnabled(CBK callbackPick)
848 switch (callbackPick)
864 // incremented every time a load notification is successfully handled -
865 // lightweight mechanism for other threads to detect when they can start
866 // referrring to new structures.
867 private long loadNotifiesHandled = 0;
869 public long getLoadNotifiesHandled()
871 return loadNotifiesHandled;
874 public void notifyFileLoaded(String fullPathName, String fileName2,
875 String modelName, String errorMsg, int modelParts)
877 if (errorMsg != null)
879 fileLoadingError = errorMsg;
883 // TODO: deal sensibly with models loaded inLine:
884 // modelName will be null, as will fullPathName.
886 // the rest of this routine ignores the arguments, and simply interrogates
887 // the Jmol view to find out what structures it contains, and adds them to
888 // the structure selection manager.
889 fileLoadingError = null;
890 String[] oldmodels = modelFileNames;
891 modelFileNames = null;
892 boolean notifyLoaded = false;
893 String[] modelfilenames = getStructureFiles();
894 // first check if we've lost any structures
895 if (oldmodels != null && oldmodels.length > 0)
898 for (int i = 0; i < oldmodels.length; i++)
900 for (int n = 0; n < modelfilenames.length; n++)
902 if (modelfilenames[n] == oldmodels[i])
908 if (oldmodels[i] != null)
915 String[] oldmfn = new String[oldm];
917 for (int i = 0; i < oldmodels.length; i++)
919 if (oldmodels[i] != null)
921 oldmfn[oldm++] = oldmodels[i];
924 // deregister the Jmol instance for these structures - we'll add
925 // ourselves again at the end for the current structure set.
926 getSsm().removeStructureViewerListener(this, oldmfn);
930 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
932 String fileName = modelfilenames[modelnum];
933 boolean foundEntry = false;
934 StructureFile pdb = null;
935 String pdbfile = null;
936 // model was probably loaded inline - so check the pdb file hashcode
939 // calculate essential attributes for the pdb data imported inline.
940 // prolly need to resolve modelnumber properly - for now just use our
942 pdbfile = jmolViewer.getData(
943 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
945 // search pdbentries and sequences to find correct pdbentry for this
947 for (int pe = 0; pe < getPdbCount(); pe++)
949 boolean matches = false;
950 addSequence(pe, getSequence()[pe]);
951 if (fileName == null)
954 // see JAL-623 - need method of matching pasted data up
956 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
957 pdbfile, DataSourceType.PASTE,
958 getIProgressIndicator());
959 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
966 File fl = new File(getPdbEntry(pe).getFile());
967 matches = fl.equals(new File(fileName));
971 // TODO: Jmol can in principle retrieve from CLASSLOADER but
974 // to be tested. See mantis bug
975 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
976 DataSourceType protocol = DataSourceType.URL;
981 protocol = DataSourceType.FILE;
983 } catch (Exception e)
988 // Explicitly map to the filename used by Jmol ;
989 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
990 fileName, protocol, getIProgressIndicator());
991 // pdbentry[pe].getFile(), protocol);
997 // add an entry for every chain in the model
998 for (int i = 0; i < pdb.getChains().size(); i++)
1000 String chid = pdb.getId() + ":"
1001 + pdb.getChains().elementAt(i).id;
1002 addChainFile(chid, fileName);
1003 getChainNames().add(chid);
1005 notifyLoaded = true;
1009 if (!foundEntry && associateNewStructs)
1011 // this is a foreign pdb file that jalview doesn't know about - add
1012 // it to the dataset and try to find a home - either on a matching
1013 // sequence or as a new sequence.
1014 String pdbcontent = jmolViewer.getData("/" + (modelnum + 1) + ".1",
1016 // parse pdb file into a chain, etc.
1017 // locate best match for pdb in associated views and add mapping to
1019 // if properly registered then
1020 notifyLoaded = true;
1025 // so finally, update the jmol bits and pieces
1026 // if (jmolpopup != null)
1028 // // potential for deadlock here:
1029 // // jmolpopup.updateComputedMenus();
1031 if (!isLoadingFromArchive())
1033 jmolViewer.evalStringQuiet(
1034 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1036 // register ourselves as a listener and notify the gui that it needs to
1038 getSsm().addStructureViewerListener(this);
1041 FeatureRenderer fr = getFeatureRenderer(null);
1047 loadNotifiesHandled++;
1049 setLoadingFromArchive(false);
1052 protected IProgressIndicator getIProgressIndicator()
1057 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1059 notifyAtomPicked(iatom, strMeasure, null);
1062 public abstract void notifyScriptTermination(String strStatus,
1066 * display a message echoed from the jmol viewer
1070 public abstract void sendConsoleEcho(String strEcho); /*
1071 * { showConsole(true);
1073 * history.append("\n" +
1077 // /End JmolStatusListener
1078 // /////////////////////////////
1082 * status message - usually the response received after a script
1085 public abstract void sendConsoleMessage(String strStatus);
1088 public void setCallbackFunction(String callbackType,
1089 String callbackFunction)
1091 System.err.println("Ignoring set-callback request to associate "
1092 + callbackType + " with function " + callbackFunction);
1096 public void showHelp()
1098 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1102 * open the URL somehow
1106 public abstract void showUrl(String url, String target);
1109 * called to show or hide the associated console window container.
1113 public abstract void showConsole(boolean show);
1116 * @param renderPanel
1118 * - when true will initialise jmol's file IO system (should be false
1119 * in applet context)
1121 * @param documentBase
1123 * @param commandOptions
1125 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1126 String htmlName, URL documentBase, URL codeBase,
1127 String commandOptions)
1129 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1130 codeBase, commandOptions, null, null);
1135 * @param renderPanel
1137 * - when true will initialise jmol's file IO system (should be false
1138 * in applet context)
1140 * @param documentBase
1142 * @param commandOptions
1143 * @param consolePanel
1144 * - panel to contain Jmol console
1145 * @param buttonsToShow
1146 * - buttons to show on the console, in ordr
1148 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1149 String htmlName, URL documentBase, URL codeBase,
1150 String commandOptions, final Container consolePanel,
1151 String buttonsToShow)
1153 if (commandOptions == null)
1155 commandOptions = "";
1157 jmolViewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1158 (jmolfileio ? new SmarterJmolAdapter() : null),
1159 htmlName + ((Object) this).toString(), documentBase, codeBase,
1160 commandOptions, this);
1162 jmolViewer.setJmolStatusListener(this); // extends JmolCallbackListener
1164 console = createJmolConsole(consolePanel, buttonsToShow);
1165 if (consolePanel != null)
1167 consolePanel.addComponentListener(this);
1173 protected abstract JmolAppConsoleInterface createJmolConsole(
1174 Container consolePanel, String buttonsToShow);
1176 protected org.jmol.api.JmolAppConsoleInterface console = null;
1179 public int[] resizeInnerPanel(String data)
1181 // Jalview doesn't honour resize panel requests
1188 protected void closeConsole()
1190 if (console != null)
1194 console.setVisible(false);
1197 } catch (Exception x)
1206 * ComponentListener method
1209 public void componentMoved(ComponentEvent e)
1214 * ComponentListener method
1217 public void componentResized(ComponentEvent e)
1222 * ComponentListener method
1225 public void componentShown(ComponentEvent e)
1231 * ComponentListener method
1234 public void componentHidden(ComponentEvent e)
1240 protected int getModelNoForFile(String pdbFile)
1242 if (modelFileNames == null)
1246 for (int i = 0; i < modelFileNames.length; i++)
1248 if (modelFileNames[i].equalsIgnoreCase(pdbFile))