JAL-3390 showSelectedChains pulled up to base class for Jmol/Chimera
[jalview.git] / src / jalview / ext / jmol / JalviewJmolBinding.java
index 50aba62..d820273 100644 (file)
  */
 package jalview.ext.jmol;
 
+import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureRenderer;
-import jalview.api.SequenceRenderer;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
+import jalview.ext.rbvi.chimera.AtomSpecModel;
+import jalview.gui.IProgressIndicator;
 import jalview.io.DataSourceType;
 import jalview.io.StructureFile;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ResidueProperties;
 import jalview.structure.AtomSpec;
-import jalview.structure.StructureMappingcommandSet;
 import jalview.structure.StructureSelectionManager;
 import jalview.structures.models.AAStructureBindingModel;
 import jalview.util.MessageManager;
@@ -43,12 +44,12 @@ import java.awt.event.ComponentEvent;
 import java.awt.event.ComponentListener;
 import java.io.File;
 import java.net.URL;
-import java.security.AccessControlException;
 import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.StringTokenizer;
 import java.util.Vector;
 
 import org.jmol.adapter.smarter.SmarterJmolAdapter;
@@ -64,6 +65,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         implements JmolStatusListener, JmolSelectionListener,
         ComponentListener
 {
+  private String lastMessage;
+
   boolean allChainsSelected = false;
 
   /*
@@ -72,7 +75,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    */
   private boolean associateNewStructs = false;
 
-  Vector<String> atomsPicked = new Vector<String>();
+  Vector<String> atomsPicked = new Vector<>();
 
   private List<String> chainNames;
 
@@ -88,8 +91,6 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
   String lastCommand;
 
-  String lastMessage;
-
   boolean loadedInline;
 
   StringBuffer resetLastRes = new StringBuffer();
@@ -132,17 +133,17 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   }
 
   /**
-   * prepare the view for a given set of models/chains. chainList contains
-   * strings of the form 'pdbfilename:Chaincode'
+   * prepare the view for a given set of models/chains. chainList contains strings
+   * of the form 'pdbfilename:Chaincode'
    * 
-   * @param chainList
-   *          list of chains to make visible
+   * @deprecated now only used by applet code
    */
-  public void centerViewer(Vector<String> chainList)
+  @Deprecated
+  public void centerViewer()
   {
     StringBuilder cmd = new StringBuilder(128);
     int mlength, p;
-    for (String lbl : chainList)
+    for (String lbl : chainsToShow)
     {
       mlength = 0;
       do
@@ -158,7 +159,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     {
       cmd.setLength(cmd.length() - 4);
     }
-    evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
+    String command = "select *;restrict " + cmd + ";cartoon;center " + cmd;
+    evalStateCommand(command);
   }
 
   public void closeViewer()
@@ -477,36 +479,47 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     lastCommand = command;
   }
 
+  Thread colourby = null;
+  
   /**
    * Sends a set of colour commands to the structure viewer
    * 
-   * @param colourBySequenceCommands
+   * @param commands
    */
   @Override
-  protected void colourBySequence(
-          StructureMappingcommandSet[] colourBySequenceCommands)
+  protected void colourBySequence(final String[] commands)
   {
-    for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
+    if (colourby != null)
     {
-      for (String cbyseq : cpdbbyseq.commands)
+      colourby.interrupt();
+      colourby = null;
+    }
+    colourby = new Thread(new Runnable()
+    {
+      @Override
+      public void run()
       {
-        executeWhenReady(cbyseq);
+        for (String cmd : commands)
+        {
+          executeWhenReady(cmd);
+        }
       }
-    }
+    });
+    colourby.start();
   }
 
   /**
    * @param files
-   * @param sr
    * @param viewPanel
    * @return
    */
   @Override
-  protected StructureMappingcommandSet[] getColourBySequenceCommands(
-          String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
+  protected String[] getColourBySequenceCommands(
+          String[] files, AlignmentViewPanel viewPanel)
   {
-    return JmolCommands.getColourBySequenceCommand(getSsm(), files,
-            getSequence(), sr, viewPanel);
+    Map<Object, AtomSpecModel> map = buildColoursMap(viewPanel);
+
+    return JmolCommands.getColourBySequenceCommand(map);
   }
 
   /**
@@ -599,78 +612,10 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    */
   private int _modelFileNameMap[];
 
-  // ////////////////////////////////
-  // /StructureListener
-  // @Override
-  public synchronized String[] getPdbFilex()
-  {
-    if (viewer == null)
-    {
-      return new String[0];
-    }
-    if (modelFileNames == null)
-    {
-      List<String> mset = new ArrayList<String>();
-      _modelFileNameMap = new int[viewer.ms.mc];
-      String m = viewer.ms.getModelFileName(0);
-      if (m != null)
-      {
-        String filePath = m;
-        try
-        {
-          filePath = new File(m).getAbsolutePath();
-        } catch (AccessControlException x)
-        {
-          // usually not allowed to do this in applet
-          System.err.println(
-                  "jmolBinding: Using local file string from Jmol: " + m);
-        }
-        if (filePath.indexOf("/file:") != -1)
-        {
-          // applet path with docroot - discard as format won't match pdbfile
-          filePath = m;
-        }
-        mset.add(filePath);
-        _modelFileNameMap[0] = 0; // filename index for first model is always 0.
-      }
-      int j = 1;
-      for (int i = 1; i < viewer.ms.mc; i++)
-      {
-        m = viewer.ms.getModelFileName(i);
-        String filePath = m;
-        if (m != null)
-        {
-          try
-          {
-            filePath = new File(m).getAbsolutePath();
-          } catch (AccessControlException x)
-          {
-            // usually not allowed to do this in applet, so keep raw handle
-            // System.err.println("jmolBinding: Using local file string from
-            // Jmol: "+m);
-          }
-        }
-
-        /*
-         * add this model unless it is read from a structure file we have
-         * already seen (example: 2MJW is an NMR structure with 10 models)
-         */
-        if (!mset.contains(filePath))
-        {
-          mset.add(filePath);
-          _modelFileNameMap[j] = i; // record the model index for the filename
-          j++;
-        }
-      }
-      modelFileNames = mset.toArray(new String[mset.size()]);
-    }
-    return modelFileNames;
-  }
-
   @Override
   public synchronized String[] getStructureFiles()
   {
-    List<String> mset = new ArrayList<String>();
+    List<String> mset = new ArrayList<>();
     if (viewer == null)
     {
       return new String[0];
@@ -807,7 +752,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     viewer.openStringInline(string);
   }
 
-  public void mouseOverStructure(int atomIndex, String strInfo)
+  protected void mouseOverStructure(int atomIndex, final String strInfo)
   {
     int pdbResNum;
     int alocsep = strInfo.indexOf("^");
@@ -861,34 +806,63 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       try
       {
         // recover PDB filename for the model hovered over.
-        int _mp = _modelFileNameMap.length - 1,
-                mnumber = new Integer(mdlId).intValue() - 1;
-        while (mnumber < _modelFileNameMap[_mp])
+        int mnumber = Integer.valueOf(mdlId).intValue() - 1;
+        if (_modelFileNameMap != null)
         {
-          _mp--;
+          int _mp = _modelFileNameMap.length - 1;
+
+          while (mnumber < _modelFileNameMap[_mp])
+          {
+            _mp--;
+          }
+          pdbfilename = modelFileNames[_mp];
         }
-        pdbfilename = modelFileNames[_mp];
-        if (pdbfilename == null)
+        else
         {
-          pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
-                  .getAbsolutePath();
-        }
+          if (mnumber >= 0 && mnumber < modelFileNames.length)
+          {
+            pdbfilename = modelFileNames[mnumber];
+          }
 
+          if (pdbfilename == null)
+          {
+            pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
+                    .getAbsolutePath();
+          }
+        }
       } catch (Exception e)
       {
       }
-      ;
     }
-    if (lastMessage == null || !lastMessage.equals(strInfo))
+
+    /*
+     * highlight position on alignment(s); if some text is returned, 
+     * show this as a second line on the structure hover tooltip
+     */
+    String label = getSsm().mouseOverStructure(pdbResNum, chainId,
+            pdbfilename);
+    if (label != null)
     {
-      getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
+      // change comma to pipe separator (newline token for Jmol)
+      label = label.replace(',', '|');
+      StringTokenizer toks = new StringTokenizer(strInfo, " ");
+      StringBuilder sb = new StringBuilder();
+      sb.append("select ").append(String.valueOf(pdbResNum)).append(":")
+              .append(chainId).append("/1");
+      sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
+              .append(toks.nextToken());
+      sb.append("|").append(label).append("\"");
+      evalStateCommand(sb.toString());
     }
-
-    lastMessage = strInfo;
   }
 
   public void notifyAtomHovered(int atomIndex, String strInfo, String data)
   {
+    if (strInfo.equals(lastMessage))
+    {
+      return;
+    }
+    lastMessage = strInfo;
     if (data != null)
     {
       System.err.println("Ignoring additional hover info: " + data
@@ -1060,8 +1034,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     fileLoadingError = null;
     String[] oldmodels = modelFileNames;
     modelFileNames = null;
-    chainNames = new ArrayList<String>();
-    chainFile = new Hashtable<String, String>();
+    chainNames = new ArrayList<>();
+    chainFile = new Hashtable<>();
     boolean notifyLoaded = false;
     String[] modelfilenames = getStructureFiles();
     // first check if we've lost any structures
@@ -1127,7 +1101,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
           // see JAL-623 - need method of matching pasted data up
           {
             pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
-                    pdbfile, DataSourceType.PASTE);
+                    pdbfile, DataSourceType.PASTE,
+                    getIProgressIndicator());
             getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
             matches = true;
             foundEntry = true;
@@ -1159,7 +1134,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
             }
             // Explicitly map to the filename used by Jmol ;
             pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
-                    fileName, protocol);
+                    fileName, protocol, getIProgressIndicator());
             // pdbentry[pe].getFile(), protocol);
 
           }
@@ -1227,6 +1202,11 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     return chainNames;
   }
 
+  protected IProgressIndicator getIProgressIndicator()
+  {
+    return null;
+  }
+
   public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
   {
     notifyAtomPicked(iatom, strMeasure, null);
@@ -1453,4 +1433,40 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   {
     showConsole(false);
   }
+
+  @Override
+  public void showStructures(AlignViewportI av, boolean refocus)
+  {
+    StringBuilder cmd = new StringBuilder(128);
+
+    if (isShowAlignmentOnly())
+    {
+      cmd.append("hide *;");
+
+      AtomSpecModel model = getShownResidues(av);
+      String atomSpec = JmolCommands.getAtomSpec(model);
+
+      cmd.append("display ").append(atomSpec);
+    }
+    else
+    {
+      cmd.append("display *");
+    }
+    cmd.append("; cartoon");
+    if (refocus)
+    {
+      cmd.append("; zoom 0");
+    }
+    evalStateCommand(cmd.toString());
+  }
+
+  /**
+   * Answers a Jmol syntax style structure model specification. Model number 0, 1,
+   * 2... is formatted as "1.1", "2.1", "3.1" etc.
+   */
+  @Override
+  public String getModelSpec(int model)
+  {
+    return String.valueOf(model + 1) + ".1";
+  }
 }