Clover icon

Coverage Report

  1. Project Clover database Thu Nov 28 2024 11:45:30 GMT
  2. Package jalview.ext.jmol

File JalviewJmolBinding.java

 

Coverage histogram

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

Code metrics

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

Classes

Class Line # Actions
JalviewJmolBinding 66 309 150
0.5404858654%
 

Contributing tests

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