Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 16:11:35 GMT
  2. Package jalview.ext.jmol

File JalviewJmolBinding.java

 

Coverage histogram

../../../img/srcFileCovDistChart6.png
37% of files have more coverage

Code metrics

136
309
49
1
1,157
786
150
0.49
6.31
49
3.06

Classes

Class Line # Actions
JalviewJmolBinding 64 309 150
0.5384615753.8%
 

Contributing tests

This file is covered by 60 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
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.
11    *
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.
16    *
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.
20    */
21    package jalview.ext.jmol;
22   
23    import java.awt.Container;
24    import java.awt.event.ComponentEvent;
25    import java.awt.event.ComponentListener;
26    import java.io.File;
27    import java.net.URL;
28    import java.util.ArrayList;
29    import java.util.Arrays;
30    import java.util.HashMap;
31    import java.util.List;
32    import java.util.Map;
33    import java.util.StringTokenizer;
34    import java.util.Vector;
35   
36    import javax.swing.SwingUtilities;
37    import org.jmol.adapter.smarter.SmarterJmolAdapter;
38    import org.jmol.api.JmolAppConsoleInterface;
39    import org.jmol.api.JmolSelectionListener;
40    import org.jmol.api.JmolStatusListener;
41    import org.jmol.api.JmolViewer;
42    import org.jmol.c.CBK;
43    import org.jmol.viewer.Viewer;
44   
45    import jalview.api.AlignmentViewPanel;
46    import jalview.api.FeatureRenderer;
47    import jalview.api.FeatureSettingsModelI;
48    import jalview.api.SequenceRenderer;
49    import jalview.bin.Console;
50    import jalview.datamodel.PDBEntry;
51    import jalview.datamodel.SequenceI;
52    import jalview.gui.AppJmol;
53    import jalview.gui.IProgressIndicator;
54    import jalview.gui.StructureViewer.ViewerType;
55    import jalview.io.DataSourceType;
56    import jalview.io.StructureFile;
57    import jalview.structure.AtomSpec;
58    import jalview.structure.StructureCommand;
59    import jalview.structure.StructureCommandI;
60    import jalview.structure.StructureSelectionManager;
61    import jalview.structures.models.AAStructureBindingModel;
62    import jalview.ws.dbsources.Pdb;
63    import javajs.util.BS;
 
64    public abstract class JalviewJmolBinding extends AAStructureBindingModel
65    implements JmolStatusListener, JmolSelectionListener,
66    ComponentListener
67    {
68    private String lastMessage;
69   
70   
71    /*
72    * when true, try to search the associated datamodel for sequences that are
73    * associated with any unknown structures in the Jmol view.
74    */
75    private boolean associateNewStructs = false;
76   
77    private Vector<String> atomsPicked = new Vector<>();
78   
79    private String lastCommand;
80   
81    private boolean loadedInline;
82   
83    private StringBuffer resetLastRes = new StringBuffer();
84   
85    public Viewer jmolViewer;
86   
 
87  50 toggle public JalviewJmolBinding(StructureSelectionManager ssm,
88    PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
89    DataSourceType protocol)
90    {
91  50 super(ssm, pdbentry, sequenceIs, protocol);
92  50 setStructureCommands(new JmolCommands());
93    /*
94    * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
95    * "jalviewJmol", ap.av.applet .getDocumentBase(), ap.av.applet.getCodeBase(),
96    * "", this);
97    *
98    * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
99    */
100    }
101   
 
102  0 toggle public JalviewJmolBinding(StructureSelectionManager ssm,
103    SequenceI[][] seqs, Viewer theViewer)
104    {
105  0 super(ssm, seqs);
106   
107  0 jmolViewer = theViewer;
108  0 jmolViewer.setJmolStatusListener(this);
109  0 jmolViewer.addSelectionListener(this);
110  0 setStructureCommands(new JmolCommands());
111    }
112   
113    /**
114    * construct a title string for the viewer window based on the data jalview
115    * knows about
116    *
117    * @return
118    */
 
119  50 toggle public String getViewerTitle()
120    {
121  50 return getDynamicViewerTitle("Jmol", true);
122    }
123   
 
124  58 toggle private String jmolScript(String script)
125    {
126  58 return jmolScript(script, false);
127    }
128   
 
129  1179 toggle private String jmolScript(String script, boolean useScriptWait)
130    {
131  1179 Console.debug(">>Jmol>> " + script);
132  1179 String s;
133  1179 if (useScriptWait)
134    {
135  3 s = jmolViewer.scriptWait(script);
136    }
137    else
138    {
139  1176 s = jmolViewer.evalStringQuiet(script); // scriptWait(script); BH
140    }
141  1174 Console.debug("<<Jmol<< " + s);
142   
143  1174 return s;
144    }
145   
 
146  437 toggle @Override
147    public List<String> executeCommand(StructureCommandI command,
148    boolean getReply)
149    {
150  437 if (command == null)
151    {
152  0 return null;
153    }
154   
155  437 String cmd = command.getCommand();
156  437 jmolHistory(false);
157  431 if (lastCommand == null || !lastCommand.equals(cmd))
158    {
159  252 jmolScript(cmd + "\n", command.isWaitNeeded());
160    }
161  431 jmolHistory(true);
162  432 lastCommand = cmd;
163  432 return null;
164    }
165   
 
166  0 toggle public void createImage(String file, String type, int quality)
167    {
168  0 jalview.bin.Console.outPrintln("JMOL CREATE IMAGE");
169    }
170   
 
171  6 toggle @Override
172    public String createImage(String fileName, String type,
173    Object textOrBytes, int quality)
174    {
175  6 jalview.bin.Console.outPrintln("JMOL CREATE IMAGE");
176  6 return null;
177    }
178   
 
179  0 toggle @Override
180    public String eval(String strEval)
181    {
182    // jalview.bin.Console.outPrintln(strEval);
183    // "# 'eval' is implemented only for the applet.";
184  0 return null;
185    }
186   
187    // End StructureListener
188    // //////////////////////////
189   
190    ////////////////////////////
191    // HETATM get
192    //
193   
 
194  66 toggle @Override
195    public Map<String, String> getHetatmNames()
196    {
197  66 HashMap<String, String> hetlist = new HashMap();
198  157 for (int mc = 0; mc < jmolViewer.ms.mc; mc++)
199    {
200  91 Map<String, String> hets = jmolViewer.ms.getHeteroList(mc);
201  91 if (hets != null)
202    {
203  13 hetlist.putAll(hets);
204    }
205    }
206  66 return hetlist;
207    }
208    //
209    ////////////////////////////
210   
 
211  0 toggle @Override
212    public float[][] functionXY(String functionName, int x, int y)
213    {
214  0 return null;
215    }
216   
 
217  0 toggle @Override
218    public float[][][] functionXYZ(String functionName, int nx, int ny,
219    int nz)
220    {
221    // TODO Auto-generated method stub
222  0 return null;
223    }
224   
225   
226    /**
227    * map between index of model filename returned from getPdbFile and the first
228    * index of models from this file in the viewer. Note - this is not trimmed -
229    * use getPdbFile to get number of unique models.
230    */
231    private int _modelFileNameMap[];
232   
 
233  1205 toggle @Override
234    public synchronized String[] getStructureFiles()
235    {
236  1205 if (jmolViewer == null)
237    {
238  54 return new String[0];
239    }
240   
241  1151 if (modelFileNames == null)
242    {
243  249 int modelCount = jmolViewer.ms.mc;
244  249 String filePath = null;
245  249 List<String> mset = new ArrayList<>();
246  522 for (int i = 0; i < modelCount; ++i)
247    {
248    /*
249    * defensive check for null as getModelFileName can return null even when model
250    * count ms.mc is > 0
251    */
252  273 filePath = jmolViewer.ms.getModelFileName(i);
253  273 if (filePath != null && !mset.contains(filePath))
254    {
255  118 mset.add(filePath);
256    }
257    }
258  249 if (!mset.isEmpty())
259    {
260  94 modelFileNames = mset.toArray(new String[mset.size()]);
261    }
262    }
263   
264  1151 return modelFileNames;
265    }
266   
267    /**
268    * map from string to applet
269    */
 
270  0 toggle @Override
271    public Map<String, Object> getRegistryInfo()
272    {
273    // TODO Auto-generated method stub
274  0 return null;
275    }
276   
277    // ///////////////////////////////
278    // JmolStatusListener
279   
 
280  0 toggle public void handlePopupMenu(int x, int y)
281    {
282    // jmolpopup.show(x, y);
283    // jmolpopup.jpiShow(x, y);
284    }
285   
286    /**
287    * Highlight zero, one or more atoms on the structure
288    */
 
289  0 toggle @Override
290    public void highlightAtoms(List<AtomSpec> atoms)
291    {
292  0 if (atoms != null)
293    {
294  0 if (resetLastRes.length() > 0)
295    {
296  0 jmolScript(resetLastRes.toString());
297  0 resetLastRes.setLength(0);
298    }
299  0 StringBuilder highlightCommands = null;
300  0 for (AtomSpec atom : atoms)
301    {
302  0 StringBuilder thisAtom = highlightAtom(atom.getAtomIndex(),
303    atom.getPdbResNum(), atom.getChain(), atom.getPdbFile());
304  0 if (thisAtom != null)
305    {
306  0 if (highlightCommands == null)
307    {
308  0 highlightCommands = thisAtom;
309    }
310    else
311    {
312  0 highlightCommands.append(thisAtom);
313    }
314    }
315    }
316  0 if (highlightCommands != null)
317    {
318  0 jmolHistory(false);
319  0 jmolScript(highlightCommands.toString());
320  0 jmolHistory(true);
321    }
322    // Highlight distances between atoms with a 'measure' command - not yet
323    // working
324    // if (atoms.size() >= 2)
325    // {
326    // StringBuilder sb = new StringBuilder();
327    // for (int a = 0; a < atoms.size(); a++)
328    // {
329    // AtomSpec speca = atoms.get(a);
330    // String a_model = getModelIdForFile(speca.getPdbFile());
331    // for (int b = a + 1; b < atoms.size(); b++)
332    // {
333    // AtomSpec specb = atoms.get(b);
334    // String b_model = getModelIdForFile(speca.getPdbFile());
335    // sb.append("measure ALL (" + speca.getAtomIndex() + " and */"
336    // + a_model + ") (" + specb.getAtomIndex() + " and */"
337    // + b_model + ");");
338    // }
339    // }
340    // jmolHistory(false, useScriptWait);
341    // jmolScript(sb.toString(), useScriptWait);
342    // jmolHistory(true, useScriptWait);
343    // }
344   
345    }
346   
347    }
348   
349    // jmol/ssm only
 
350  0 toggle private StringBuilder highlightAtom(int atomIndex, int pdbResNum,
351    String chain, String pdbfile)
352    {
353  0 String modelId = getModelIdForFile(pdbfile);
354  0 if (modelId.isEmpty())
355    {
356  0 return null;
357    }
358   
359  0 StringBuilder selection = new StringBuilder(32);
360  0 StringBuilder cmd = new StringBuilder(64);
361  0 selection.append("select ").append(String.valueOf(pdbResNum));
362  0 selection.append(":");
363  0 if (!chain.equals(" "))
364    {
365  0 selection.append(chain);
366    }
367  0 selection.append(" /").append(modelId);
368   
369  0 cmd.append(selection).append(";wireframe 100;").append(selection)
370    .append(" and not hetero;").append("spacefill 200;select none");
371   
372  0 resetLastRes.append(selection).append(";wireframe 0;").append(selection)
373    .append(" and not hetero; spacefill 0;");
374   
375  0 return cmd;
376    }
377   
378    private boolean debug = true;
379   
 
380  868 toggle private void jmolHistory(boolean enable)
381    {
382  868 jmolHistory(enable, false);
383    }
384   
 
385  868 toggle private void jmolHistory(boolean enable, boolean useScriptWait)
386    {
387  869 jmolScript("History " + ((debug || enable) ? "on" : "off"),
388    useScriptWait);
389    }
390   
 
391  0 toggle public void loadInline(String string)
392    {
393  0 loadedInline = true;
394    // TODO: re JAL-623
395    // viewer.loadInline(strModel, isAppend);
396    // could do this:
397    // construct fake fullPathName and fileName so we can identify the file
398    // later.
399    // Then, construct pass a reader for the string to Jmol.
400    // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
401    // fileName, null, reader, false, null, null, 0);
402  0 jmolViewer.openStringInline(string);
403    }
404   
 
405  1 toggle protected void mouseOverStructure(int atomIndex, final String strInfo)
406    {
407  1 int pdbResNum;
408  1 int alocsep = strInfo.indexOf("^");
409  1 int mdlSep = strInfo.indexOf("/");
410  1 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
411   
412  1 if (chainSeparator == -1)
413    {
414  0 chainSeparator = strInfo.indexOf(".");
415  0 if (mdlSep > -1 && mdlSep < chainSeparator)
416    {
417  0 chainSeparator1 = chainSeparator;
418  0 chainSeparator = mdlSep;
419    }
420    }
421    // handle insertion codes
422  1 if (alocsep != -1)
423    {
424  0 pdbResNum = Integer.parseInt(
425    strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
426   
427    }
428    else
429    {
430  1 pdbResNum = Integer.parseInt(
431    strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
432    }
433  1 String chainId;
434   
435  1 if (strInfo.indexOf(":") > -1)
436    {
437  1 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
438    strInfo.indexOf("."));
439    }
440    else
441    {
442  0 chainId = " ";
443    }
444   
445  1 String pdbfilename = modelFileNames[0]; // default is first model
446  1 if (mdlSep > -1)
447    {
448  1 if (chainSeparator1 == -1)
449    {
450  1 chainSeparator1 = strInfo.indexOf(".", mdlSep);
451    }
452  1 String mdlId = (chainSeparator1 > -1)
453    ? strInfo.substring(mdlSep + 1, chainSeparator1)
454    : strInfo.substring(mdlSep + 1);
455  1 try
456    {
457    // recover PDB filename for the model hovered over.
458  1 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
459  1 if (_modelFileNameMap != null)
460    {
461  0 int _mp = _modelFileNameMap.length - 1;
462   
463  0 while (mnumber < _modelFileNameMap[_mp])
464    {
465  0 _mp--;
466    }
467  0 pdbfilename = modelFileNames[_mp];
468    }
469    else
470    {
471  1 if (mnumber >= 0 && mnumber < modelFileNames.length)
472    {
473  1 pdbfilename = modelFileNames[mnumber];
474    }
475   
476  1 if (pdbfilename == null)
477    {
478  0 pdbfilename = new File(jmolViewer.ms.getModelFileName(mnumber))
479    .getAbsolutePath();
480    }
481    }
482    } catch (Exception e)
483    {
484    }
485    }
486   
487    /*
488    * highlight position on alignment(s); if some text is returned, show this as a
489    * second line on the structure hover tooltip
490    */
491  1 String label = getSsm().mouseOverStructure(pdbResNum, chainId,
492    pdbfilename);
493  1 if (label != null)
494    {
495    // change comma to pipe separator (newline token for Jmol)
496  0 label = label.replace(',', '|');
497  0 StringTokenizer toks = new StringTokenizer(strInfo, " ");
498  0 StringBuilder sb = new StringBuilder();
499  0 sb.append("select ").append(String.valueOf(pdbResNum)).append(":")
500    .append(chainId).append("/1");
501  0 sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
502    .append(toks.nextToken());
503  0 sb.append("|").append(label).append("\"");
504  0 executeCommand(new StructureCommand(sb.toString()), false);
505    }
506    }
507   
 
508  0 toggle public void notifyAtomHovered(int atomIndex, String strInfo, String data)
509    {
510  0 if (strInfo.equals(lastMessage))
511    {
512  0 return;
513    }
514  0 lastMessage = strInfo;
515  0 if (data != null)
516    {
517  0 jalview.bin.Console.errPrintln(
518    "Ignoring additional hover info: " + data + " (other info: '"
519    + strInfo + "' pos " + atomIndex + ")");
520    }
521  0 mouseOverStructure(atomIndex, strInfo);
522    }
523   
524    /*
525    * { if (history != null && strStatus != null &&
526    * !strStatus.equals("Script completed")) { history.append("\n" + strStatus); }
527    * }
528    */
529   
 
530  0 toggle public void notifyAtomPicked(int atomIndex, String strInfo,
531    String strData)
532    {
533    /**
534    * this implements the toggle label behaviour copied from the original
535    * structure viewer, mc_view
536    */
537  0 if (strData != null)
538    {
539  0 jalview.bin.Console.errPrintln(
540    "Ignoring additional pick data string " + strData);
541    }
542  0 int chainSeparator = strInfo.indexOf(":");
543  0 int p = 0;
544  0 if (chainSeparator == -1)
545    {
546  0 chainSeparator = strInfo.indexOf(".");
547    }
548   
549  0 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
550    chainSeparator);
551  0 String mdlString = "";
552  0 if ((p = strInfo.indexOf(":")) > -1)
553    {
554  0 picked += strInfo.substring(p, strInfo.indexOf("."));
555    }
556   
557  0 if ((p = strInfo.indexOf("/")) > -1)
558    {
559  0 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
560    }
561  0 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
562    + mdlString + "))";
563  0 jmolHistory(false);
564   
565  0 if (!atomsPicked.contains(picked))
566    {
567  0 jmolScript("select " + picked + ";label %n %r:%c");
568  0 atomsPicked.addElement(picked);
569    }
570    else
571    {
572  0 jmolViewer.evalString("select " + picked + ";label off");
573  0 atomsPicked.removeElement(picked);
574    }
575  0 jmolHistory(true);
576    // TODO: in application this happens
577    //
578    // if (scriptWindow != null)
579    // {
580    // scriptWindow.sendConsoleMessage(strInfo);
581    // scriptWindow.sendConsoleMessage("\n");
582    // }
583   
584    }
585   
 
586  248 toggle @Override
587    public void notifyCallback(CBK type, Object[] data)
588    {
589    /*
590    * ensure processed in AWT thread to avoid risk of deadlocks
591    */
592  248 SwingUtilities.invokeLater(new Runnable()
593    {
594   
 
595  248 toggle @Override
596    public void run()
597    {
598  248 processCallback(type, data);
599    }
600    });
601    }
602   
603    /**
604    * Processes one callback notification from Jmol
605    *
606    * @param type
607    * @param data
608    */
 
609  248 toggle protected void processCallback(CBK type, Object[] data)
610    {
611  248 try
612    {
613  248 switch (type)
614    {
615  79 case LOADSTRUCT:
616  79 notifyFileLoaded((String) data[1], (String) data[2],
617    (String) data[3], (String) data[4],
618    ((Integer) data[5]).intValue());
619   
620  79 break;
621  0 case PICK:
622  0 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
623    (String) data[0]);
624    // also highlight in alignment
625    // deliberate fall through
626  0 case HOVER:
627  0 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
628    (String) data[0]);
629  0 break;
630  12 case SCRIPT:
631  12 notifyScriptTermination((String) data[2],
632    ((Integer) data[3]).intValue());
633  12 break;
634  49 case ECHO:
635  49 sendConsoleEcho((String) data[1]);
636  49 break;
637  0 case MESSAGE:
638  0 sendConsoleMessage(
639  0 (data == null) ? ((String) null) : (String) data[1]);
640  0 break;
641  0 case ERROR:
642    // jalview.bin.Console.errPrintln("Ignoring error callback.");
643  0 break;
644  96 case SYNC:
645  0 case RESIZE:
646  96 refreshGUI();
647  96 break;
648  12 case MEASURE:
649   
650  0 case CLICK:
651  0 default:
652  12 jalview.bin.Console.errPrintln(
653    "Unhandled callback " + type + " " + data[1].toString());
654  12 break;
655    }
656    } catch (Exception e)
657    {
658  0 jalview.bin.Console
659    .errPrintln("Squashed Jmol callback handler error:");
660  0 e.printStackTrace();
661    }
662    }
663   
 
664  511 toggle @Override
665    public boolean notifyEnabled(CBK callbackPick)
666    {
667  511 switch (callbackPick)
668    {
669  49 case ECHO:
670  79 case LOADSTRUCT:
671  12 case MEASURE:
672  0 case MESSAGE:
673  0 case PICK:
674  12 case SCRIPT:
675  0 case HOVER:
676  0 case ERROR:
677  152 return true;
678  359 default:
679  359 return false;
680    }
681    }
682   
683    // incremented every time a load notification is successfully handled -
684    // lightweight mechanism for other threads to detect when they can start
685    // referrring to new structures.
686    private long loadNotifiesHandled = 0;
687   
 
688  105 toggle public long getLoadNotifiesHandled()
689    {
690  105 return loadNotifiesHandled;
691    }
692   
 
693  79 toggle public void notifyFileLoaded(String fullPathName, String fileName2,
694    String modelName, String errorMsg, int modelParts)
695    {
696  79 if (errorMsg != null)
697    {
698  12 fileLoadingError = errorMsg;
699  12 refreshGUI();
700  12 return;
701    }
702    // TODO: deal sensibly with models loaded inLine:
703    // modelName will be null, as will fullPathName.
704   
705    // the rest of this routine ignores the arguments, and simply interrogates
706    // the Jmol view to find out what structures it contains, and adds them to
707    // the structure selection manager.
708  67 fileLoadingError = null;
709  67 String[] oldmodels = modelFileNames;
710  67 modelFileNames = null;
711  67 boolean notifyLoaded = false;
712  67 String[] modelfilenames = getStructureFiles();
713  67 if (modelfilenames == null)
714    {
715    // Jmol is still loading files!
716  3 return;
717    }
718  64 if (jalview.bin.Console.isTraceEnabled())
719    {
720  0 jalview.bin.Console.trace("New structures loaded in Jmol:");
721  0 int i=1;
722  0 for (String mfn: modelfilenames)
723    {
724  0 jalview.bin.Console.trace(i++ +" "+((mfn==null) ? "NULL" : mfn));
725    }
726    }
727    // first check if we've lost any structures
728  64 if (oldmodels != null && oldmodels.length > 0)
729    {
730  44 int oldm = 0;
731  97 for (int i = 0; i < oldmodels.length; i++)
732    {
733  66 for (int n = 0; n < modelfilenames.length; n++)
734    {
735  66 if (modelfilenames[n] == oldmodels[i])
736    {
737  53 oldmodels[i] = null;
738  53 break;
739    }
740    }
741  53 if (oldmodels[i] != null)
742    {
743  0 oldm++;
744    }
745    }
746  44 if (oldm > 0)
747    {
748  0 String[] oldmfn = new String[oldm];
749  0 oldm = 0;
750  0 for (int i = 0; i < oldmodels.length; i++)
751    {
752  0 if (oldmodels[i] != null)
753    {
754  0 oldmfn[oldm++] = oldmodels[i];
755    }
756    }
757    // deregister the Jmol instance for these structures - we'll add
758    // ourselves again at the end for the current structure set.
759  0 getSsm().removeStructureViewerListener(this, oldmfn);
760    }
761    }
762  64 refreshPdbEntries();
763  144 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
764    {
765  80 String fileName = modelfilenames[modelnum];
766  80 boolean foundEntry = false;
767  80 StructureFile pdb = null;
768  80 String pdbfile = null;
769    // model was probably loaded inline - so check the pdb file hashcode
770  80 if (loadedInline)
771    {
772    // calculate essential attributes for the pdb data imported inline.
773    // prolly need to resolve modelnumber properly - for now just use our
774    // 'best guess'
775  0 pdbfile = jmolViewer.getData(
776    "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
777    }
778    // search pdbentries and sequences to find correct pdbentry for this
779    // model
780  204 for (int pe = 0; pe < getPdbCount(); pe++)
781    {
782  124 boolean matches = false;
783  124 addSequence(pe, getSequence()[pe]);
784  124 if (fileName == null)
785    {
786  0 if (false)
787    // see JAL-623 - need method of matching pasted data up
788    {
789    // ALSO need to use the PDBEntry based setMapping method to pass in other metadata
790  0 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
791    pdbfile, DataSourceType.PASTE, getIProgressIndicator());
792  0 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
793  0 matches = true;
794  0 foundEntry = true;
795    }
796    }
797    else
798    {
799  124 String jvPdbFile = getPdbEntry(pe).getFile();
800  124 File fl = new File(jvPdbFile);
801  124 matches = fl.equals(new File(fileName)) || JmolCommands.filePathMatch(fileName, jvPdbFile);
802  124 if (matches)
803    {
804  77 foundEntry = true;
805    // TODO: Jmol can in principle retrieve from CLASSLOADER but
806    // this
807    // needs
808    // to be tested. See mantis bug
809    // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
810  77 DataSourceType protocol = DataSourceType.URL;
811  77 try
812    {
813  77 if (fl.exists())
814    {
815  74 protocol = DataSourceType.FILE;
816    }
817    } catch (Exception e)
818    {
819    } catch (Error e)
820    {
821    }
822    // Explicitly map to the filename used by Jmol ;
823  77 pdb = getSsm().setMapping(true,getSequence()[pe], getPdbEntry(pe), getChains()[pe],
824    getIProgressIndicator());
825    // pdbentry[pe].getFile(), protocol);
826   
827    }
828    }
829  124 if (matches)
830    {
831  77 stashFoundChains(pdb, fileName);
832  77 notifyLoaded = true;
833    }
834    }
835   
836  80 if (!foundEntry && associateNewStructs)
837    {
838    // this is a foreign pdb file that jalview doesn't know about - add
839    // it to the dataset and try to find a home - either on a matching
840    // sequence or as a new sequence.
841  0 String pdbcontent = jmolViewer.getData("/" + (modelnum + 1) + ".1",
842    "PDB");
843    // parse pdb file into a chain, etc.
844    // locate best match for pdb in associated views and add mapping to
845    // ssm
846    // if properly registered then
847  0 notifyLoaded = true;
848   
849    }
850    }
851    // FILE LOADED OK
852    // so finally, update the jmol bits and pieces
853    // if (jmolpopup != null)
854    // {
855    // // potential for deadlock here:
856    // // jmolpopup.updateComputedMenus();
857    // }
858  64 if (!isLoadingFromArchive())
859    {
860  58 jmolScript(
861    "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
862    }
863    // register ourselves as a listener and notify the gui that it needs to
864    // update itself.
865  64 getSsm().addStructureViewerListener(this);
866  64 if (notifyLoaded)
867    {
868  61 FeatureRenderer fr = getFeatureRenderer(null);
869  61 if (fr != null)
870    {
871  49 FeatureSettingsModelI colours = new Pdb().getFeatureColourScheme();
872  49 ((AppJmol) getViewer()).getAlignmentPanel().av
873    .applyFeaturesStyle(colours);
874    }
875  61 refreshGUI();
876  61 loadNotifiesHandled++;
877    }
878  64 setLoadingFromArchive(false);
879    }
880   
881   
 
882  77 toggle protected IProgressIndicator getIProgressIndicator()
883    {
884  77 return null;
885    }
886   
 
887  0 toggle public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
888    {
889  0 notifyAtomPicked(iatom, strMeasure, null);
890    }
891   
892    public abstract void notifyScriptTermination(String strStatus,
893    int msWalltime);
894   
895    /**
896    * display a message echoed from the jmol viewer
897    *
898    * @param strEcho
899    */
900    public abstract void sendConsoleEcho(String strEcho); /*
901    * { showConsole(true);
902    *
903    * history.append("\n" + strEcho); }
904    */
905   
906    // /End JmolStatusListener
907    // /////////////////////////////
908   
909    /**
910    * @param strStatus
911    * status message - usually the response received after a script
912    * executed
913    */
914    public abstract void sendConsoleMessage(String strStatus);
915   
 
916  0 toggle @Override
917    public void setCallbackFunction(String callbackType,
918    String callbackFunction)
919    {
920  0 jalview.bin.Console
921    .errPrintln("Ignoring set-callback request to associate "
922    + callbackType + " with function " + callbackFunction);
923   
924    }
925   
926   
 
927  0 toggle public void showHelp()
928    {
929  0 showUrl("http://wiki.jmol.org"
930    // BH 2018 "http://jmol.sourceforge.net/docs/JmolUserGuide/"
931    , "jmolHelp");
932    }
933   
934    /**
935    * open the URL somehow
936    *
937    * @param target
938    */
939    public abstract void showUrl(String url, String target);
940   
941    /**
942    * called to show or hide the associated console window container.
943    *
944    * @param show
945    */
946    public abstract void showConsole(boolean show);
947   
 
948  211 toggle public static Viewer getJmolData(JmolParser jmolParser)
949    {
950  211 return (Viewer) JmolViewer.allocateViewer(null, null, null, null, null,
951    "-x -o -n", jmolParser);
952    }
953   
954    /**
955    *
956    *
957    *
958    * @param renderPanel
959    * @param jmolfileio
960    * - when true will initialise jmol's file IO system (should be false
961    * in applet context)
962    * @param htmlName
963    * @param documentBase
964    * @param codeBase
965    * @param commandOptions
966    */
 
967  0 toggle public void allocateViewer(Container renderPanel, boolean jmolfileio,
968    String htmlName, URL documentBase, URL codeBase,
969    String commandOptions)
970    {
971  0 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
972    codeBase, commandOptions, null, null);
973    }
974   
975    /**
976    *
977    * @param renderPanel
978    * @param jmolfileio
979    * - when true will initialise jmol's file IO system (should be false
980    * in applet context)
981    * @param htmlName
982    * @param documentBase
983    * @param codeBase
984    * @param commandOptions
985    * @param consolePanel
986    * - panel to contain Jmol console
987    * @param buttonsToShow
988    * - buttons to show on the console, in order
989    */
 
990  50 toggle public void allocateViewer(Container renderPanel, boolean jmolfileio,
991    String htmlName, URL documentBase, URL codeBase,
992    String commandOptions, final Container consolePanel,
993    String buttonsToShow)
994    {
995   
996  50 jalview.bin.Console
997    .errPrintln("Allocating Jmol Viewer: " + commandOptions);
998   
999  50 if (commandOptions == null)
1000    {
1001  0 commandOptions = "";
1002    }
1003  50 jmolViewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1004  50 (jmolfileio ? new SmarterJmolAdapter() : null),
1005    htmlName + ((Object) this).toString(), documentBase, codeBase,
1006    commandOptions, this);
1007   
1008  50 jmolViewer.setJmolStatusListener(this); // extends JmolCallbackListener
1009   
1010  50 try
1011    {
1012  50 console = createJmolConsole(consolePanel, buttonsToShow);
1013    } catch (Throwable e)
1014    {
1015  0 jalview.bin.Console
1016    .errPrintln("Could not create Jmol application console. "
1017    + e.getMessage());
1018  0 e.printStackTrace();
1019    }
1020  50 if (consolePanel != null)
1021    {
1022  50 consolePanel.addComponentListener(this);
1023   
1024    }
1025   
1026    }
1027   
1028    protected abstract JmolAppConsoleInterface createJmolConsole(
1029    Container consolePanel, String buttonsToShow);
1030   
1031    // BH 2018 -- Jmol console is not working due to problems with styled
1032    // documents.
1033   
1034    protected org.jmol.api.JmolAppConsoleInterface console = null;
1035   
 
1036  0 toggle @Override
1037    public int[] resizeInnerPanel(String data)
1038    {
1039    // Jalview doesn't honour resize panel requests
1040  0 return null;
1041    }
1042   
1043    /**
1044    *
1045    */
 
1046  48 toggle protected void closeConsole()
1047    {
1048  48 if (console != null)
1049    {
1050  48 try
1051    {
1052  48 console.setVisible(false);
1053    } catch (Error e)
1054    {
1055    } catch (Exception x)
1056    {
1057    }
1058  48 ;
1059  48 console = null;
1060    }
1061    }
1062   
1063    /**
1064    * ComponentListener method
1065    */
 
1066  0 toggle @Override
1067    public void componentMoved(ComponentEvent e)
1068    {
1069    }
1070   
1071    /**
1072    * ComponentListener method
1073    */
 
1074  0 toggle @Override
1075    public void componentResized(ComponentEvent e)
1076    {
1077    }
1078   
1079    /**
1080    * ComponentListener method
1081    */
 
1082  0 toggle @Override
1083    public void componentShown(ComponentEvent e)
1084    {
1085  0 showConsole(true);
1086    }
1087   
1088    /**
1089    * ComponentListener method
1090    */
 
1091  0 toggle @Override
1092    public void componentHidden(ComponentEvent e)
1093    {
1094  0 showConsole(false);
1095    }
1096   
1097   
 
1098  379 toggle @Override
1099    protected String getModelIdForFile(String pdbFile)
1100    {
1101  379 if (modelFileNames == null)
1102    {
1103  0 return "";
1104    }
1105  535 for (int i = 0; i < modelFileNames.length; i++)
1106    {
1107  535 if (JmolCommands.filePathMatch(modelFileNames[i],pdbFile))
1108    {
1109  379 return String.valueOf(i + 1);
1110    }
1111    }
1112  0 return "";
1113    }
1114   
 
1115  3 toggle @Override
1116    protected ViewerType getViewerType()
1117    {
1118  3 return ViewerType.JMOL;
1119    }
1120   
 
1121  0 toggle @Override
1122    protected String getModelId(int pdbfnum, String file)
1123    {
1124  0 return String.valueOf(pdbfnum + 1);
1125    }
1126   
1127    /**
1128    * Returns ".spt" - the Jmol session file extension
1129    *
1130    * @return
1131    * @see https://chemapps.stolaf.edu/jmol/docs/#writemodel
1132    */
 
1133  3 toggle @Override
1134    public String getSessionFileExtension()
1135    {
1136  3 return ".spt";
1137    }
1138   
 
1139  0 toggle @Override
1140    public void selectionChanged(BS arg0)
1141    {
1142    // TODO Auto-generated method stub
1143   
1144    }
1145   
 
1146  0 toggle @Override
1147    public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp)
1148    {
1149  0 return new jalview.gui.SequenceRenderer(avp.getAlignViewport());
1150    }
1151   
 
1152  0 toggle @Override
1153    public String getHelpURL()
1154    {
1155  0 return "http://wiki.jmol.org"; // BH 2018
1156    }
1157    }