JAL-621 - also renamed list of javascript handlers
[jalview.git] / src / jalview / bin / JalviewLite.java
index dd2bf70..1801eb1 100755 (executable)
@@ -22,6 +22,7 @@ import jalview.appletgui.EmbmenuFrame;
 import jalview.appletgui.FeatureSettings;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Sequence;
@@ -67,8 +68,8 @@ public class JalviewLite extends Applet
   // The following public methods maybe called
   // externally, eg via javascript in HTML page
   /**
-   * @return String list of selected sequence IDs, each terminated by the 'boolean not' character (""+0x00AC) or
-   *         (¬)
+   * @return String list of selected sequence IDs, each terminated by the
+   *         'boolean not' character (""+0x00AC) or (¬)
    */
   public String getSelectedSequences()
   {
@@ -78,7 +79,8 @@ public class JalviewLite extends Applet
   /**
    * @param sep
    *          separator string or null for default
-   * @return String list of selected sequence IDs, each terminated by given separator string
+   * @return String list of selected sequence IDs, each terminated by given
+   *         separator string
    */
   public String getSelectedSequences(String sep)
   {
@@ -88,12 +90,13 @@ public class JalviewLite extends Applet
   /**
    * @param alf
    *          alignframe containing selection
-   * @return String list of selected sequence IDs, each terminated by current default separator sequence
+   * @return String list of selected sequence IDs, each terminated by current
+   *         default separator sequence
    * 
    */
   public String getSelectedSequencesFrom(AlignFrame alf)
   {
-    return getSelectedSequencesFrom(alf,separator); // ""+0x00AC);
+    return getSelectedSequencesFrom(alf, separator); // ""+0x00AC);
   }
 
   /**
@@ -141,7 +144,8 @@ public class JalviewLite extends Applet
   public void highlight(String sequenceId, String position,
           String alignedPosition)
   {
-    highlightIn(getDefaultTargetFrame(), sequenceId, position, alignedPosition);
+    highlightIn(getDefaultTargetFrame(), sequenceId, position,
+            alignedPosition);
   }
 
   /**
@@ -154,12 +158,13 @@ public class JalviewLite extends Applet
    *          false, blank or something else - indicate if position is an
    *          alignment column or unaligned sequence position
    */
-  public void highlightIn(AlignFrame alf, String sequenceId, String position,
-          String alignedPosition)
+  public void highlightIn(AlignFrame alf, String sequenceId,
+          String position, String alignedPosition)
   {
     // TODO: could try to highlight in all alignments if alf==null
-    SequenceI sq = alf.getAlignViewport().getAlignment()
-            .findName(sequenceId);
+    jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
+            alf.viewport.getAlignment().getSequencesArray());
+    SequenceI sq = matcher.findIdMatch(sequenceId);
     if (sq != null)
     {
       int pos, apos = -1;
@@ -244,10 +249,13 @@ public class JalviewLite extends Applet
     if (sep == null || sep.length() == 0)
     {
       sep = separator;
-    } else {
+    }
+    else
+    {
       if (debug)
       {
-        System.err.println("Selecting region using separator string '"+separator+"'");
+        System.err.println("Selecting region using separator string '"
+                + separator + "'");
       }
     }
     // deparse fields
@@ -256,22 +264,28 @@ public class JalviewLite extends Applet
     SequenceGroup sel = new SequenceGroup();
     ColumnSelection csel = new ColumnSelection();
     AlignmentI al = alf.viewport.getAlignment();
+    jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
+            alf.viewport.getAlignment().getSequencesArray());
     int start = 0, end = al.getWidth(), alw = al.getWidth();
+    boolean seqsfound = true;
     if (ids != null && ids.length > 0)
     {
+      seqsfound = false;
       for (int i = 0; i < ids.length; i++)
       {
         if (ids[i].trim().length() == 0)
         {
           continue;
         }
-        SequenceI sq = al.findName(ids[i]);
+        SequenceI sq = matcher.findIdMatch(ids[i]);
         if (sq != null)
         {
+          seqsfound = true;
           sel.addSequence(sq, false);
         }
       }
     }
+    boolean inseqpos = false;
     if (cols != null && cols.length > 0)
     {
       boolean seset = false;
@@ -363,10 +377,18 @@ public class JalviewLite extends Applet
             r--;
           } catch (NumberFormatException ex)
           {
-            System.err
-                    .println("ERROR: Couldn't parse integer from point selection element of column selection string '"
-                            + cl + "'");
-            return;
+            if (cl.toLowerCase().equals("sequence"))
+            {
+              // we are in the dataset sequence's coordinate frame.
+              inseqpos = true;
+            }
+            else
+            {
+              System.err
+                      .println("ERROR: Couldn't parse integer from point selection element of column selection string '"
+                              + cl + "'");
+              return;
+            }
           }
           if (r >= 0 && r <= alw)
           {
@@ -403,10 +425,31 @@ public class JalviewLite extends Applet
         }
       }
     }
-    sel.setStartRes(start);
-    sel.setEndRes(end);
-    alf.select(sel, csel);
-
+    if (seqsfound)
+    {
+      // we only propagate the selection when it was the null selection, or the
+      // given sequences were found in the alignment.
+      if (inseqpos && sel.getSize() > 0)
+      {
+        // assume first sequence provides reference frame ?
+        SequenceI rs = sel.getSequenceAt(0);
+        start = rs.findIndex(start);
+        end = rs.findIndex(end);
+        if (csel != null)
+        {
+          Vector cs = csel.getSelected();
+          csel.clear();
+          for (int csi = 0, csiS = cs.size(); csi < csiS; csi++)
+          {
+            csel.addElement(rs.findIndex(((Integer) cs.elementAt(csi))
+                    .intValue()));
+          }
+        }
+      }
+      sel.setStartRes(start);
+      sel.setEndRes(end);
+      alf.select(sel, csel);
+    }
   }
 
   /**
@@ -424,8 +467,8 @@ public class JalviewLite extends Applet
    */
   public String getSelectedSequencesAsAlignment(String format, String suffix)
   {
-    return getSelectedSequencesAsAlignmentFrom(getDefaultTargetFrame(), format,
-            suffix);
+    return getSelectedSequencesAsAlignmentFrom(getDefaultTargetFrame(),
+            format, suffix);
   }
 
   /**
@@ -462,6 +505,86 @@ public class JalviewLite extends Applet
     return "";
   }
 
+  public String getAlignmentOrder()
+  {
+    return getAlignmentOrderFrom(getDefaultTargetFrame());
+  }
+
+  public String getAlignmentOrderFrom(AlignFrame alf)
+  {
+    return getAlignmentOrderFrom(alf, separator);
+  }
+
+  public String getAlignmentOrderFrom(AlignFrame alf, String sep)
+  {
+    AlignmentI alorder = alf.getAlignViewport().getAlignment();
+    String[] order = new String[alorder.getHeight()];
+    for (int i = 0; i < order.length; i++)
+    {
+      order[i] = alorder.getSequenceAt(i).getName();
+    }
+    return arrayToSeparatorList(order);
+  }
+
+  public String orderBy(String order, String undoName)
+  {
+    return orderBy(order, undoName, separator);
+  }
+
+  public String orderBy(String order, String undoName, String sep)
+  {
+    return orderAlignmentBy(getDefaultTargetFrame(), order, undoName, sep);
+  }
+
+  public String orderAlignmentBy(AlignFrame alf, String order,
+          String undoName, String sep)
+  {
+    String[] ids = separatorListToArray(order, sep);
+    SequenceI[] sqs = null;
+    if (ids != null && ids.length > 0)
+    {
+      jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
+              alf.viewport.getAlignment().getSequencesArray());
+      int s = 0;
+      sqs = new SequenceI[ids.length];
+      for (int i = 0; i < ids.length; i++)
+      {
+        if (ids[i].trim().length() == 0)
+        {
+          continue;
+        }
+        SequenceI sq = matcher.findIdMatch(ids[i]);
+        if (sq != null)
+        {
+          sqs[s++] = sq;
+        }
+      }
+      if (s > 0)
+      {
+        SequenceI[] sqq = new SequenceI[s];
+        System.arraycopy(sqs, 0, sqq, 0, s);
+        sqs = sqq;
+      }
+      else
+      {
+        sqs = null;
+      }
+    }
+    if (sqs == null)
+    {
+      return "";
+    }
+    ;
+    AlignmentOrder aorder = new AlignmentOrder(sqs);
+
+    if (undoName != null && undoName.trim().length() == 0)
+    {
+      undoName = null;
+    }
+
+    return alf.sortBy(aorder, undoName) ? "true" : "";
+  }
+
   public String getAlignment(String format)
   {
     return getAlignmentFrom(getDefaultTargetFrame(), format, "true");
@@ -587,7 +710,7 @@ public class JalviewLite extends Applet
     setMouseoverListener(currentAlignFrame, listener);
   }
 
-  private Vector mouseoverListeners = new Vector();
+  private Vector javascriptListeners = new Vector();
 
   public void setMouseoverListener(AlignFrame af, String listener)
   {
@@ -603,7 +726,7 @@ public class JalviewLite extends Applet
     }
     jalview.javascript.MouseOverListener mol = new jalview.javascript.MouseOverListener(
             this, af, listener);
-    mouseoverListeners.addElement(mol);
+    javascriptListeners.addElement(mol);
     StructureSelectionManager.getStructureSelectionManager()
             .addStructureViewerListener(mol);
     if (debug)
@@ -611,7 +734,7 @@ public class JalviewLite extends Applet
       System.err.println("Added a mouseover listener for "
               + ((af == null) ? "All frames" : "Just views for "
                       + af.getAlignViewport().getSequenceSetId()));
-      System.err.println("There are now " + mouseoverListeners.size()
+      System.err.println("There are now " + javascriptListeners.size()
               + " listeners in total.");
     }
   }
@@ -635,7 +758,7 @@ public class JalviewLite extends Applet
     }
     jalview.javascript.JsSelectionSender mol = new jalview.javascript.JsSelectionSender(
             this, af, listener);
-    mouseoverListeners.addElement(mol);
+    javascriptListeners.addElement(mol);
     StructureSelectionManager.getStructureSelectionManager()
             .addSelectionListener(mol);
     if (debug)
@@ -643,11 +766,34 @@ public class JalviewLite extends Applet
       System.err.println("Added a selection listener for "
               + ((af == null) ? "All frames" : "Just views for "
                       + af.getAlignViewport().getSequenceSetId()));
-      System.err.println("There are now " + mouseoverListeners.size()
+      System.err.println("There are now " + javascriptListeners.size()
               + " listeners in total.");
     }
   }
 
+  public void setStructureListener(String listener)
+  {
+    if (listener != null)
+    {
+      listener = listener.trim();
+      if (listener.length() == 0)
+      {
+        System.err
+                .println("jalview Javascript error: Ignoring empty function for selection listener.");
+        return;
+      }
+    }
+    jalview.javascript.MouseOverStructureListener mol = new jalview.javascript.MouseOverStructureListener(this, listener);
+    javascriptListeners.addElement(mol);
+    StructureSelectionManager.getStructureSelectionManager()
+            .addStructureViewerListener(mol);
+    if (debug)
+    {
+      System.err.println("Added a javascript structure viewer listener '"+listener+"'");
+      System.err.println("There are now " + javascriptListeners.size()
+              + " listeners in total.");
+    }
+  }
   /**
    * remove any callback using the given listener function and associated with
    * the given alignFrame (or null for all callbacks)
@@ -668,15 +814,15 @@ public class JalviewLite extends Applet
       }
     }
     boolean rprt = false;
-    for (int ms = 0, msSize = mouseoverListeners.size(); ms < msSize;)
+    for (int ms = 0, msSize = javascriptListeners.size(); ms < msSize;)
     {
-      Object lstn = mouseoverListeners.elementAt(ms);
+      Object lstn = javascriptListeners.elementAt(ms);
       JsCallBack lstner = (JsCallBack) lstn;
       if ((af == null || lstner.getAlignFrame() == af)
               && (listener == null || lstner.getListenerFunction().equals(
                       listener)))
       {
-        mouseoverListeners.removeElement(lstner);
+        javascriptListeners.removeElement(lstner);
         msSize--;
         if (lstner instanceof SelectionListener)
         {
@@ -701,19 +847,19 @@ public class JalviewLite extends Applet
     }
     if (rprt)
     {
-      System.err.println("There are now " + mouseoverListeners.size()
+      System.err.println("There are now " + javascriptListeners.size()
               + " listeners in total.");
     }
   }
 
   public void stop()
   {
-    if (mouseoverListeners != null)
+    if (javascriptListeners != null)
     {
-      while (mouseoverListeners.size() > 0)
+      while (javascriptListeners.size() > 0)
       {
-        Object mol = mouseoverListeners.elementAt(0);
-        mouseoverListeners.removeElement(mol);
+        Object mol = javascriptListeners.elementAt(0);
+        javascriptListeners.removeElement(mol);
         if (mol instanceof SelectionListener)
         {
           StructureSelectionManager.getStructureSelectionManager()
@@ -737,10 +883,19 @@ public class JalviewLite extends Applet
    * @param chain
    * @param pdbfile
    */
-  public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
+  public void mouseOverStructure(String pdbResNum, String chain, String pdbfile)
   {
+    try {
     StructureSelectionManager.getStructureSelectionManager()
-            .mouseOverStructure(pdbResNum, chain, pdbfile);
+            .mouseOverStructure(new Integer(pdbResNum).intValue(), chain, pdbfile);
+    if (debug)
+    {
+      System.err.println("mouseOver for '"+pdbResNum+"' in chain '"+chain+"' in structure '"+pdbfile+"'");
+    }
+    } catch (NumberFormatException e)
+    {
+        System.err.println("Ignoring invalid residue number string '"+pdbResNum+"'");
+    }
   }
 
   // //////////////////////////////////////////////
@@ -782,6 +937,11 @@ public class JalviewLite extends Applet
 
   private boolean alignPdbStructures = false;
 
+  /**
+   * use an external structure viewer exclusively (no jmols or MCViews will be opened by JalviewLite itself)
+   */
+  public boolean useXtrnalSviewer=false;
+
   public static boolean debug = false;
 
   static String builddate = null, version = null;
@@ -842,17 +1002,21 @@ public class JalviewLite extends Applet
     // remove any handlers that might be hanging around from an earlier instance
     try
     {
-      if (getAppletContext() instanceof sun.plugin.javascript.JSContext) {
-        if (debug)
-        {
-          System.err.println("Applet context implements JSContext - should have callback support!");
-        }
+      if (debug)
+      {
+        System.err.println("Applet context is '"
+                + getAppletContext().getClass().toString() + "'");
       }
-       JSObject scriptObject = JSObject.getWindow(this);  
+      JSObject scriptObject = JSObject.getWindow(this);
+      if (debug && scriptObject != null)
+      {
+        System.err.println("Applet has Javascript callback support.");
+      }
+
     } catch (Exception ex)
     {
       System.err
-      .println("Warning: No JalviewLite javascript callbacks available.");
+              .println("Warning: No JalviewLite javascript callbacks available.");
       if (debug)
       {
         ex.printStackTrace();
@@ -873,6 +1037,11 @@ public class JalviewLite extends Applet
       System.err.println("Build Date : " + getBuildDate());
 
     }
+    String externalsviewer = getParameter("externalstructureviewer");
+    if (externalsviewer!=null)
+    {
+      useXtrnalSviewer=externalsviewer.trim().toLowerCase().equals("true");
+    }
     /**
      * if true disable the check for jmol
      */
@@ -927,7 +1096,7 @@ public class JalviewLite extends Applet
     }
 
     setBackground(new Color(r, g, b));
-    
+
     file = getParameter("file");
 
     if (file == null)
@@ -958,8 +1127,7 @@ public class JalviewLite extends Applet
     else if (file != null)
     {
       if (getParameter("showbutton") == null
-              || !getParameter("showbutton").equalsIgnoreCase(
-                      "false"))
+              || !getParameter("showbutton").equalsIgnoreCase("false"))
       {
         // Add the JalviewLite 'Button' to the page
         add(launcher);
@@ -999,18 +1167,22 @@ public class JalviewLite extends Applet
     initjscallback = initjscallback.trim();
     if (initjscallback.length() > 0)
     {
-      JSObject scriptObject = null; 
-      try {
+      JSObject scriptObject = null;
+      try
+      {
         scriptObject = JSObject.getWindow(this);
-      } catch (Exception ex) {};
+      } catch (Exception ex)
+      {
+      }
+      ;
       if (scriptObject != null)
       {
         try
         {
           // do onInit with the JS executor thread
           new JSFunctionExec(this).executeJavascriptFunction(true,
-                  initjscallback, null, "Calling oninit callback '" + initjscallback
-                  + "'.");
+                  initjscallback, null, "Calling oninit callback '"
+                          + initjscallback + "'.");
         } catch (Exception e)
         {
           System.err.println("Exception when executing _oninit callback '"
@@ -1124,6 +1296,7 @@ public class JalviewLite extends Applet
       g.drawString("Loading Data...", 50, getSize().height / 2);
     }
   }
+
   /**
    * get all components associated with the applet of the given type
    * 
@@ -1447,6 +1620,10 @@ public class JalviewLite extends Applet
         // Accumulate pdbs here if they are heading for the same view (if
         // alignPdbStructures is true)
         Vector pdbs = new Vector();
+        // create a lazy matcher if we're asked to
+        jalview.analysis.SequenceIdMatcher matcher = (applet.getDefaultParameter("relaxedidmatch", false)) ? new jalview.analysis.SequenceIdMatcher(
+                newAlignFrame.getAlignViewport().getAlignment().getSequencesArray()) : null;
+
         do
         {
           if (pdbFileCount > 0)
@@ -1469,8 +1646,8 @@ public class JalviewLite extends Applet
               String sequence = applet.getParameter("PDBSEQ");
               if (sequence != null)
                 seqs = new SequenceI[]
-                { (Sequence) newAlignFrame.getAlignViewport()
-                        .getAlignment().findName(sequence) };
+                { matcher==null ? (Sequence) newAlignFrame.getAlignViewport()
+                        .getAlignment().findName(sequence) : matcher.findIdMatch(sequence) };
 
             }
             else
@@ -1489,8 +1666,8 @@ public class JalviewLite extends Applet
                   tmp2.addElement(st2.nextToken());
                   seqstring = st2.nextToken();
                 }
-                tmp.addElement((Sequence) newAlignFrame.getAlignViewport()
-                        .getAlignment().findName(seqstring));
+                tmp.addElement(matcher==null ? (Sequence) newAlignFrame.getAlignViewport()
+                        .getAlignment().findName(seqstring) : matcher.findIdMatch(seqstring));
               }
 
               seqs = new SequenceI[tmp.size()];
@@ -1663,8 +1840,10 @@ public class JalviewLite extends Applet
   /**
    * separator used for separatorList
    */
-  protected String separator = ""+((char)0x00AC); // the default used to be '|' but many sequence IDS include pipes.
-  
+  protected String separator = "" + ((char) 0x00AC); // the default used to be
+                                                     // '|' but many sequence
+                                                     // IDS include pipes.
+
   /**
    * parse the string into a list
    * 
@@ -1866,15 +2045,15 @@ public class JalviewLite extends Applet
    */
   public void setSeparator(String separator)
   {
-    if (separator==null || separator.length()<1)
+    if (separator == null || separator.length() < 1)
     {
       // reset to default
-      separator = ""+((char)0x00AC);
+      separator = "" + ((char) 0x00AC);
     }
     this.separator = separator;
     if (debug)
     {
-      System.err.println("Default Separator now: '"+separator+"'");
+      System.err.println("Default Separator now: '" + separator + "'");
     }
   }