JAL-3269 ready for testing embedded interface
[jalview.git] / src / jalview / bin / JalviewLite.java
index aec0a5e..75b0add 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.bin;
 
 import jalview.analysis.AlignmentUtils;
+import jalview.api.AlignFrameI;
 import jalview.api.AlignViewportI;
 import jalview.api.JalviewApp;
 import jalview.api.StructureSelectionManagerProvider;
@@ -33,6 +34,7 @@ import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
@@ -48,10 +50,14 @@ import jalview.javascript.JSFunctionExec;
 import jalview.javascript.JalviewLiteJsApi;
 import jalview.javascript.JsCallBack;
 import jalview.javascript.MouseOverStructureListener;
+import jalview.renderer.seqfeatures.FeatureRenderer;
 import jalview.structure.SelectionListener;
+import jalview.structure.SelectionSource;
 import jalview.structure.StructureSelectionManager;
+import jalview.structure.VamsasSource;
 import jalview.util.ColorUtils;
 import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
 
 import java.applet.Applet;
 import java.awt.Button;
@@ -81,6 +87,7 @@ import netscape.javascript.JSObject;
  * @author $author$
  * @version $Revision: 1.92 $
  */
+@SuppressWarnings("serial")
 public class JalviewLite extends Applet
         implements StructureSelectionManagerProvider, JalviewLiteJsApi,
         JalviewApp
@@ -99,6 +106,12 @@ public class JalviewLite extends Applet
     return StructureSelectionManager.getStructureSelectionManager(this);
   }
 
+  @Override
+  public StructureSelectionManagerProvider getStructureSelectionManagerProvider()
+  {
+    return this;
+  }
+
   // /////////////////////////////////////////
   // The following public methods may be called
   // externally, eg via javascript in HTML page
@@ -132,7 +145,7 @@ public class JalviewLite extends Applet
    * .AlignFrame)
    */
   @Override
-  public String getSelectedSequencesFrom(AlignFrame alf)
+  public String getSelectedSequencesFrom(AlignFrameI alf)
   {
     return getSelectedSequencesFrom(alf, separator); // ""+0x00AC);
   }
@@ -145,17 +158,18 @@ public class JalviewLite extends Applet
    * .AlignFrame, java.lang.String)
    */
   @Override
-  public String getSelectedSequencesFrom(AlignFrame alf, String sep)
+  public String getSelectedSequencesFrom(AlignFrameI alf, String sep)
   {
     StringBuffer result = new StringBuffer("");
     if (sep == null || sep.length() == 0)
     {
       sep = separator; // "+0x00AC;
     }
-    if (alf.viewport.getSelectionGroup() != null)
+    if (((AlignFrame) alf).viewport.getSelectionGroup() != null)
     {
-      SequenceI[] seqs = alf.viewport.getSelectionGroup()
-              .getSequencesInOrder(alf.viewport.getAlignment());
+      SequenceI[] seqs = ((AlignFrame) alf).viewport.getSelectionGroup()
+              .getSequencesInOrder(
+                      ((AlignFrame) alf).viewport.getAlignment());
 
       for (int i = 0; i < seqs.length; i++)
       {
@@ -188,12 +202,12 @@ public class JalviewLite extends Applet
    * java.lang.String, java.lang.String, java.lang.String)
    */
   @Override
-  public void highlightIn(final AlignFrame alf, final String sequenceId,
+  public void highlightIn(final AlignFrameI alf, final String sequenceId,
           final String position, final String alignedPosition)
   {
     // TODO: could try to highlight in all alignments if alf==null
     jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
-            alf.viewport.getAlignment().getSequencesArray());
+            ((AlignFrame) alf).viewport.getAlignment().getSequencesArray());
     final SequenceI sq = matcher.findIdMatch(sequenceId);
     if (sq != null)
     {
@@ -268,7 +282,7 @@ public class JalviewLite extends Applet
    * java.lang.String, java.lang.String)
    */
   @Override
-  public void selectIn(AlignFrame alf, String sequenceIds, String columns)
+  public void selectIn(AlignFrameI alf, String sequenceIds, String columns)
   {
     selectIn(alf, sequenceIds, columns, separator);
   }
@@ -280,7 +294,7 @@ public class JalviewLite extends Applet
    * java.lang.String, java.lang.String, java.lang.String)
    */
   @Override
-  public void selectIn(final AlignFrame alf, String sequenceIds,
+  public void selectIn(final AlignFrameI alf, String sequenceIds,
           String columns, String sep)
   {
     if (sep == null || sep.length() == 0)
@@ -300,9 +314,9 @@ public class JalviewLite extends Applet
     String[] cols = JalviewAppLoader.separatorListToArray(columns, sep);
     final SequenceGroup sel = new SequenceGroup();
     final ColumnSelection csel = new ColumnSelection();
-    AlignmentI al = alf.viewport.getAlignment();
+    AlignmentI al = ((AlignFrame) alf).viewport.getAlignment();
     jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
-            alf.viewport.getAlignment().getSequencesArray());
+            ((AlignFrame) alf).viewport.getAlignment().getSequencesArray());
     int start = 0, end = al.getWidth(), alw = al.getWidth();
     boolean seqsfound = true;
     if (ids != null && ids.length > 0)
@@ -486,8 +500,8 @@ public class JalviewLite extends Applet
         @Override
         public void run()
         {
-          alf.select(sel, csel,
-                  alf.getAlignViewport().getAlignment().getHiddenColumns());
+          ((AlignFrame) alf).select(sel, csel, ((AlignFrame) alf)
+                  .getAlignViewport().getAlignment().getHiddenColumns());
         }
       });
     }
@@ -516,20 +530,21 @@ public class JalviewLite extends Applet
    * .appletgui.AlignFrame, java.lang.String, java.lang.String)
    */
   @Override
-  public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
+  public String getSelectedSequencesAsAlignmentFrom(AlignFrameI alf,
           String format, String suffix)
   {
     try
     {
       FileFormatI theFormat = FileFormats.getInstance().forName(format);
       boolean seqlimits = suffix.equalsIgnoreCase(TRUE);
-      if (alf.viewport.getSelectionGroup() != null)
+      if (((AlignFrame) alf).viewport.getSelectionGroup() != null)
       {
         // JBPNote: getSelectionAsNewSequence behaviour has changed - this
         // method now returns a full copy of sequence data
         // TODO consider using getSequenceSelection instead here
         String reply = new AppletFormatAdapter().formatSequences(theFormat,
-                new Alignment(alf.viewport.getSelectionAsNewSequence()),
+                new Alignment(((AlignFrame) alf).viewport
+                        .getSelectionAsNewSequence()),
                 seqlimits);
         return reply;
       }
@@ -561,7 +576,7 @@ public class JalviewLite extends Applet
    * )
    */
   @Override
-  public String getAlignmentOrderFrom(AlignFrame alf)
+  public String getAlignmentOrderFrom(AlignFrameI alf)
   {
     return getAlignmentOrderFrom(alf, separator);
   }
@@ -574,9 +589,10 @@ public class JalviewLite extends Applet
    * , java.lang.String)
    */
   @Override
-  public String getAlignmentOrderFrom(AlignFrame alf, String sep)
+  public String getAlignmentOrderFrom(AlignFrameI alf, String sep)
   {
-    AlignmentI alorder = alf.getAlignViewport().getAlignment();
+    AlignmentI alorder = ((AlignFrame) alf).getAlignViewport()
+            .getAlignment();
     String[] order = new String[alorder.getHeight()];
     for (int i = 0; i < order.length; i++)
     {
@@ -617,7 +633,7 @@ public class JalviewLite extends Applet
    * java.lang.String, java.lang.String, java.lang.String)
    */
   @Override
-  public String orderAlignmentBy(AlignFrame alf, String order,
+  public String orderAlignmentBy(AlignFrameI alf, String order,
           String undoName, String sep)
   {
     String[] ids = JalviewAppLoader.separatorListToArray(order, sep);
@@ -625,7 +641,8 @@ public class JalviewLite extends Applet
     if (ids != null && ids.length > 0)
     {
       jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
-              alf.viewport.getAlignment().getSequencesArray());
+              ((AlignFrame) alf).viewport.getAlignment()
+                      .getSequencesArray());
       int s = 0;
       sqs = new SequenceI[ids.length];
       for (int i = 0; i < ids.length; i++)
@@ -665,7 +682,7 @@ public class JalviewLite extends Applet
     final String _undoName = undoName;
     // TODO: deal with synchronization here: cannot raise any events until after
     // this has returned.
-    return alf.sortBy(aorder, _undoName) ? TRUE : "";
+    return ((AlignFrame) alf).sortBy(aorder, _undoName) ? TRUE : "";
   }
 
   /*
@@ -687,7 +704,7 @@ public class JalviewLite extends Applet
    * java.lang.String)
    */
   @Override
-  public String getAlignmentFrom(AlignFrame alf, String format)
+  public String getAlignmentFrom(AlignFrameI alf, String format)
   {
     return getAlignmentFrom(alf, format, TRUE);
   }
@@ -712,7 +729,7 @@ public class JalviewLite extends Applet
    * java.lang.String, java.lang.String)
    */
   @Override
-  public String getAlignmentFrom(AlignFrame alf, String format,
+  public String getAlignmentFrom(AlignFrameI alf, String format,
           String suffix)
   {
     try
@@ -721,7 +738,7 @@ public class JalviewLite extends Applet
 
       FileFormatI theFormat = FileFormats.getInstance().forName(format);
       String reply = new AppletFormatAdapter().formatSequences(theFormat,
-              alf.viewport.getAlignment(), seqlimits);
+              ((AlignFrame) alf).viewport.getAlignment(), seqlimits);
       return reply;
     } catch (IllegalArgumentException ex)
     {
@@ -750,17 +767,19 @@ public class JalviewLite extends Applet
    * , java.lang.String)
    */
   @Override
-  public void loadAnnotationFrom(AlignFrame alf, String annotation)
+  public void loadAnnotationFrom(AlignFrameI alf, String annotation)
   {
-    if (new AnnotationFile().annotateAlignmentView(alf.getAlignViewport(),
+    if (new AnnotationFile().annotateAlignmentView(
+            ((AlignFrame) alf).getAlignViewport(),
             annotation, DataSourceType.PASTE))
     {
-      alf.alignPanel.fontChanged();
-      alf.alignPanel.setScrollValues(0, 0);
+      ((AlignFrame) alf).alignPanel.fontChanged();
+      ((AlignFrame) alf).alignPanel.setScrollValues(0, 0);
     }
     else
     {
-      alf.parseFeaturesFile(annotation, DataSourceType.PASTE);
+      ((AlignFrame) alf).parseFeaturesFile(annotation,
+              DataSourceType.PASTE);
     }
   }
 
@@ -783,10 +802,11 @@ public class JalviewLite extends Applet
    * , java.lang.String)
    */
   @Override
-  public boolean loadFeaturesFrom(AlignFrame alf, String features,
+  public boolean loadFeaturesFrom(AlignFrameI alf, String features,
           boolean autoenabledisplay)
   {
-    return alf.parseFeaturesFile(features, DataSourceType.PASTE,
+    return ((AlignFrame) alf).parseFeaturesFile(features,
+            DataSourceType.PASTE,
             autoenabledisplay);
   }
 
@@ -809,9 +829,9 @@ public class JalviewLite extends Applet
    * java.lang.String)
    */
   @Override
-  public String getFeaturesFrom(AlignFrame alf, String format)
+  public String getFeaturesFrom(AlignFrameI alf, String format)
   {
-    return alf.outputFeatures(false, format);
+    return ((AlignFrame) alf).outputFeatures(false, format);
   }
 
   /*
@@ -833,9 +853,9 @@ public class JalviewLite extends Applet
    * )
    */
   @Override
-  public String getAnnotationFrom(AlignFrame alf)
+  public String getAnnotationFrom(AlignFrameI alf)
   {
-    return alf.outputAnnotations(false);
+    return ((AlignFrame) alf).outputAnnotations(false);
   }
 
   /*
@@ -866,9 +886,9 @@ public class JalviewLite extends Applet
    * @see jalview.bin.JalviewLiteJsApi#newViewFrom(jalview.appletgui.AlignFrame)
    */
   @Override
-  public AlignFrame newViewFrom(AlignFrame alf)
+  public AlignFrame newViewFrom(AlignFrameI alf)
   {
-    return alf.newView(null);
+    return ((AlignFrame) alf).newView(null);
   }
 
   /*
@@ -878,9 +898,9 @@ public class JalviewLite extends Applet
    * java.lang.String)
    */
   @Override
-  public AlignFrame newViewFrom(AlignFrame alf, String name)
+  public AlignFrame newViewFrom(AlignFrameI alf, String name)
   {
-    return alf.newView(name);
+    return ((AlignFrame) alf).newView(name);
   }
 
   /*
@@ -932,7 +952,7 @@ public class JalviewLite extends Applet
    * , java.lang.String)
    */
   @Override
-  public void setMouseoverListener(AlignFrame af, String listener)
+  public void setMouseoverListener(AlignFrameI af, String listener)
   {
     if (listener != null)
     {
@@ -945,7 +965,7 @@ public class JalviewLite extends Applet
       }
     }
     jalview.javascript.MouseOverListener mol = new jalview.javascript.MouseOverListener(
-            this, af, listener);
+            this, (AlignFrame) af, listener, debug);
     javascriptListeners.addElement(mol);
     StructureSelectionManager.getStructureSelectionManager(this)
             .addStructureViewerListener(mol);
@@ -954,7 +974,8 @@ public class JalviewLite extends Applet
       System.err.println("Added a mouseover listener for "
               + ((af == null) ? "All frames"
                       : "Just views for "
-                              + af.getAlignViewport().getSequenceSetId()));
+                              + ((AlignFrame) af).getAlignViewport()
+                                      .getSequenceSetId()));
       System.err.println("There are now " + javascriptListeners.size()
               + " listeners in total.");
     }
@@ -979,7 +1000,7 @@ public class JalviewLite extends Applet
    * , java.lang.String)
    */
   @Override
-  public void setSelectionListener(AlignFrame af, String listener)
+  public void setSelectionListener(AlignFrameI af, String listener)
   {
     if (listener != null)
     {
@@ -992,7 +1013,7 @@ public class JalviewLite extends Applet
       }
     }
     jalview.javascript.JsSelectionSender mol = new jalview.javascript.JsSelectionSender(
-            this, af, listener);
+            this, (AlignFrame) af, listener, debug);
     javascriptListeners.addElement(mol);
     StructureSelectionManager.getStructureSelectionManager(this)
             .addSelectionListener(mol);
@@ -1001,7 +1022,8 @@ public class JalviewLite extends Applet
       System.err.println("Added a selection listener for "
               + ((af == null) ? "All frames"
                       : "Just views for "
-                              + af.getAlignViewport().getSequenceSetId()));
+                              + ((AlignFrame) af).getAlignViewport()
+                                      .getSequenceSetId()));
       System.err.println("There are now " + javascriptListeners.size()
               + " listeners in total.");
     }
@@ -1032,7 +1054,7 @@ public class JalviewLite extends Applet
       }
     }
     MouseOverStructureListener mol = new MouseOverStructureListener(this,
-            listener, separatorListToArray(modelSet));
+            listener, separatorListToArray(modelSet), debug);
     javascriptListeners.addElement(mol);
     StructureSelectionManager.getStructureSelectionManager(this)
             .addStructureViewerListener(mol);
@@ -1053,7 +1075,7 @@ public class JalviewLite extends Applet
    * .AlignFrame, java.lang.String)
    */
   @Override
-  public void removeJavascriptListener(AlignFrame af, String listener)
+  public void removeJavascriptListener(AlignFrameI af, String listener)
   {
     if (listener != null)
     {
@@ -1148,11 +1170,10 @@ public class JalviewLite extends Applet
     }
     if (jsFunctionExec != null)
     {
-      jsFunctionExec.stopQueue();
-      jsFunctionExec.jvlite = null;
+      jsFunctionExec.tidyUp();
+      jsFunctionExec = null;
     }
     initialAlignFrame = null;
-    jsFunctionExec = null;
     javascriptListeners = null;
     StructureSelectionManager.release(this);
   }
@@ -1204,7 +1225,7 @@ public class JalviewLite extends Applet
    * java.lang.String, java.lang.String)
    */
   @Override
-  public void scrollViewToIn(final AlignFrame alf, final String topRow,
+  public void scrollViewToIn(final AlignFrameI alf, final String topRow,
           final String leftHandColumn)
   {
     java.awt.EventQueue.invokeLater(new Runnable()
@@ -1214,7 +1235,7 @@ public class JalviewLite extends Applet
       {
         try
         {
-          alf.scrollTo(new Integer(topRow).intValue(),
+          ((AlignFrame) alf).scrollTo(new Integer(topRow).intValue(),
                   new Integer(leftHandColumn).intValue());
 
         } catch (Exception ex)
@@ -1236,7 +1257,7 @@ public class JalviewLite extends Applet
    * .AlignFrame, java.lang.String)
    */
   @Override
-  public void scrollViewToRowIn(final AlignFrame alf, final String topRow)
+  public void scrollViewToRowIn(final AlignFrameI alf, final String topRow)
   {
 
     java.awt.EventQueue.invokeLater(new Runnable()
@@ -1246,7 +1267,7 @@ public class JalviewLite extends Applet
       {
         try
         {
-          alf.scrollToRow(new Integer(topRow).intValue());
+          ((AlignFrame) alf).scrollToRow(new Integer(topRow).intValue());
 
         } catch (Exception ex)
         {
@@ -1267,7 +1288,7 @@ public class JalviewLite extends Applet
    * .AlignFrame, java.lang.String)
    */
   @Override
-  public void scrollViewToColumnIn(final AlignFrame alf,
+  public void scrollViewToColumnIn(final AlignFrameI alf,
           final String leftHandColumn)
   {
     java.awt.EventQueue.invokeLater(new Runnable()
@@ -1278,7 +1299,8 @@ public class JalviewLite extends Applet
       {
         try
         {
-          alf.scrollToColumn(new Integer(leftHandColumn).intValue());
+          ((AlignFrame) alf)
+                  .scrollToColumn(new Integer(leftHandColumn).intValue());
 
         } catch (Exception ex)
         {
@@ -1324,9 +1346,9 @@ public class JalviewLite extends Applet
 
   boolean embedded = false;
 
-  private boolean checkForJmol = true;
+  boolean checkForJmol = true;
 
-  private boolean checkedForJmol = false; // ensure we don't check for jmol
+  boolean checkedForJmol = false; // ensure we don't check for jmol
 
   // every time the app is re-inited
 
@@ -1615,7 +1637,7 @@ public class JalviewLite extends Applet
         try
         {
           // do onInit with the JS executor thread
-          new JSFunctionExec(this).executeJavascriptFunction(true,
+          new JSFunctionExec(this, debug).executeJavascriptFunction(true,
                   initjscallback, null,
                   "Calling oninit callback '" + initjscallback + "'.");
         } catch (Exception e)
@@ -2047,7 +2069,7 @@ public class JalviewLite extends Applet
   /**
    * set to enable the URL based javascript execution mechanism
    */
-  public boolean jsfallbackEnabled = false;
+  private boolean jsfallbackEnabled = false;
 
   /**
    * parse the string into a list
@@ -2055,6 +2077,7 @@ public class JalviewLite extends Applet
    * @param list
    * @return elements separated by separator
    */
+  @Override
   public String[] separatorListToArray(String list)
   {
     return JalviewAppLoader.separatorListToArray(list, separator);
@@ -2066,49 +2089,10 @@ public class JalviewLite extends Applet
    * @param list
    * @return concatenated string
    */
+  @Override
   public String arrayToSeparatorList(String[] list)
   {
-    return arrayToSeparatorList(list, separator);
-  }
-
-  /**
-   * concatenate the list with separator
-   * 
-   * @param list
-   * @param separator
-   * @return concatenated string
-   */
-  public static String arrayToSeparatorList(String[] list, String separator)
-  {
-    // TODO use StringUtils version
-    StringBuffer v = new StringBuffer();
-    if (list != null && list.length > 0)
-    {
-      for (int i = 0, iSize = list.length; i < iSize; i++)
-      {
-        if (list[i] != null)
-        {
-          if (i > 0)
-          {
-            v.append(separator);
-          }
-          v.append(list[i]);
-        }
-      }
-      if (debug)
-      {
-        System.err
-                .println("Returning '" + separator + "' separated List:\n");
-        System.err.println(v);
-      }
-      return v.toString();
-    }
-    if (debug)
-    {
-      System.err.println(
-              "Returning empty '" + separator + "' separated List\n");
-    }
-    return "" + separator;
+    return JalviewAppLoader.arrayToSeparatorList(list, separator);
   }
 
   /*
@@ -2132,9 +2116,10 @@ public class JalviewLite extends Applet
    * )
    */
   @Override
-  public String getFeatureGroupsOn(AlignFrame alf)
+  public String getFeatureGroupsOn(AlignFrameI alf)
   {
-    String lst = arrayToSeparatorList(alf.getFeatureGroups());
+    String lst = arrayToSeparatorList(
+            ((AlignFrame) alf).getFeatureGroups());
     return lst;
   }
 
@@ -2158,9 +2143,10 @@ public class JalviewLite extends Applet
    * .AlignFrame, boolean)
    */
   @Override
-  public String getFeatureGroupsOfStateOn(AlignFrame alf, boolean visible)
+  public String getFeatureGroupsOfStateOn(AlignFrameI alf, boolean visible)
   {
-    return arrayToSeparatorList(alf.getFeatureGroupsOfState(visible));
+    return arrayToSeparatorList(
+            ((AlignFrame) alf).getFeatureGroupsOfState(visible));
   }
 
   /*
@@ -2170,7 +2156,7 @@ public class JalviewLite extends Applet
    * AlignFrame, java.lang.String, boolean)
    */
   @Override
-  public void setFeatureGroupStateOn(final AlignFrame alf,
+  public void setFeatureGroupStateOn(final AlignFrameI alf,
           final String groups, boolean state)
   {
     final boolean st = state;// !(state==null || state.equals("") ||
@@ -2180,7 +2166,8 @@ public class JalviewLite extends Applet
       @Override
       public void run()
       {
-        alf.setFeatureGroupState(separatorListToArray(groups), st);
+        ((AlignFrame) alf)
+                .setFeatureGroupState(separatorListToArray(groups), st);
       }
     });
   }
@@ -2260,10 +2247,11 @@ public class JalviewLite extends Applet
    * java.lang.String, java.lang.String, java.lang.String)
    */
   @Override
-  public boolean addPdbFile(AlignFrame alFrame, String sequenceId,
+  public boolean addPdbFile(AlignFrameI alFrame, String sequenceId,
           String pdbEntryString, String pdbFile)
   {
-    return alFrame.addPdbFile(sequenceId, pdbEntryString, pdbFile);
+    return ((AlignFrame) alFrame).addPdbFile(sequenceId, pdbEntryString,
+            pdbFile);
   }
 
   @Override
@@ -2283,86 +2271,36 @@ public class JalviewLite extends Applet
     // callInitCallback();
   }
 
-  private Hashtable<String, long[]> jshashes = new Hashtable<>();
+  private Hashtable<String, int[]> jshashes = new Hashtable<>();
 
   private Hashtable<String, Hashtable<String, String[]>> jsmessages = new Hashtable<>();
 
-  public void setJsMessageSet(String messageclass, String viewId,
-          String[] colcommands)
-  {
-    Hashtable<String, String[]> msgset = jsmessages.get(messageclass);
-    if (msgset == null)
-    {
-      msgset = new Hashtable<>();
-      jsmessages.put(messageclass, msgset);
-    }
-    msgset.put(viewId, colcommands);
-    long[] l = new long[colcommands.length];
-    for (int i = 0; i < colcommands.length; i++)
-    {
-      l[i] = colcommands[i].hashCode();
-    }
-    jshashes.put(messageclass + "|" + viewId, l);
-  }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see jalview.bin.JalviewLiteJsApi#getJsMessage(java.lang.String,
-   * java.lang.String)
-   */
   @Override
-  public String getJsMessage(String messageclass, String viewId)
+  public Hashtable<String, int[]> getJSHashes()
   {
-    Hashtable<String, String[]> msgset = jsmessages.get(messageclass);
-    if (msgset != null)
-    {
-      String[] msgs = msgset.get(viewId);
-      if (msgs != null)
-      {
-        for (int i = 0; i < msgs.length; i++)
-        {
-          if (msgs[i] != null)
-          {
-            String m = msgs[i];
-            msgs[i] = null;
-            return m;
-          }
-        }
-      }
-    }
-    return "";
+    return jshashes;
   }
 
-  public boolean isJsMessageSetChanged(String string, String string2,
-          String[] colcommands)
+  @Override
+  public Hashtable<String, Hashtable<String, String[]>> getJSMessages()
   {
-    long[] l = jshashes.get(string + "|" + string2);
-    if (l == null && colcommands != null)
-    {
-      return true;
-    }
-    for (int i = 0; i < colcommands.length; i++)
-    {
-      if (l[i] != colcommands[i].hashCode())
-      {
-        return true;
-      }
-    }
-    return false;
+    return jsmessages;
   }
 
-  private Vector jsExecQueue = new Vector();
+  private Vector<Runnable> jsExecQueue = new Vector<>();
 
-  public Vector getJsExecQueue()
+  @Override
+  public Vector<Runnable> getJsExecQueue(JSFunctionExec exec)
   {
+    jsFunctionExec = exec;
     return jsExecQueue;
   }
 
-  public void setExecutor(JSFunctionExec jsFunctionExec2)
-  {
-    jsFunctionExec = jsFunctionExec2;
-  }
+  // public void setExecutor(JSFunctionExec jsFunctionExec2)
+  // {
+  // jsFunctionExec = jsFunctionExec2;
+  // }
 
   /**
    * return the given colour value parameter or the given default if parameter
@@ -2507,21 +2445,150 @@ public class JalviewLite extends Applet
     loaderFrame.loadTree(tree, treeFile);
   }
 
-  /**
-   * bind structures in a viewer to any matching sequences in an alignFrame (use
-   * sequenceIds to limit scope of search to specific sequences)
-   * 
-   * @param alFrame
-   * @param viewer
-   * @param sequenceIds
-   * @return TODO: consider making an exception structure for indicating when
-   *         binding fails public SequenceStructureBinding
-   *         addStructureViewInstance( AlignFrame alFrame, Object viewer, String
-   *         sequenceIds) {
-   * 
-   *         if (sequenceIds != null && sequenceIds.length() > 0) { return
-   *         alFrame.addStructureViewInstance(viewer,
-   *         separatorListToArray(sequenceIds)); } else { return
-   *         alFrame.addStructureViewInstance(viewer, null); } // return null; }
-   */
+  @Override
+  public boolean isJsfallbackEnabled()
+  {
+    return jsfallbackEnabled;
+  }
+
+  @Override
+  public JSObject getJSObject()
+  {
+    return JSObject.getWindow(this);
+  }
+
+  @Override
+  public void updateColoursFromMouseOver(Object source,
+          MouseOverStructureListener listener)
+  {
+  }
+
+  @Override
+  public Object[] getSelectionForListener(SequenceGroup seqsel, ColumnSelection colsel,
+          HiddenColumns hidden, SelectionSource source, Object alignFrame)
+  {
+    // System.err.println("Testing selection event relay to
+    // jsfunction:"+_listener);
+      String setid = "";
+      AlignFrame src = (AlignFrame) alignFrame;
+      if (source != null)
+      {
+        if (source instanceof jalview.appletgui.AlignViewport
+                && ((jalview.appletgui.AlignViewport) source).applet.currentAlignFrame.viewport == source)
+        {
+          // should be valid if it just generated an event!
+          src = ((jalview.appletgui.AlignViewport) source).applet.currentAlignFrame;
+
+        }
+      }
+      String[] seqs = new String[] {};
+      String[] cols = new String[] {};
+      int strt = 0, end = (src == null) ? -1
+              : src.alignPanel.av.getAlignment().getWidth();
+      if (seqsel != null && seqsel.getSize() > 0)
+      {
+        seqs = new String[seqsel.getSize()];
+        for (int i = 0; i < seqs.length; i++)
+        {
+          seqs[i] = seqsel.getSequenceAt(i).getName();
+        }
+        if (strt < seqsel.getStartRes())
+        {
+          strt = seqsel.getStartRes();
+        }
+        if (end == -1 || end > seqsel.getEndRes())
+        {
+          end = seqsel.getEndRes();
+        }
+      }
+      if (colsel != null && !colsel.isEmpty())
+      {
+        if (end == -1)
+        {
+          end = colsel.getMax() + 1;
+        }
+        cols = new String[colsel.getSelected().size()];
+        for (int i = 0; i < cols.length; i++)
+        {
+          cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
+        }
+      }
+      else
+      {
+        if (seqsel != null && seqsel.getSize() > 0)
+        {
+          // send a valid range, otherwise we send the empty selection
+          cols = new String[2];
+          cols[0] = "" + (1 + strt) + "-" + (1 + end);
+        }
+      }
+      return  new Object[]
+    { src, setid, arrayToSeparatorList(seqs), arrayToSeparatorList(cols) };
+  }
+
+  @Override
+  public String getJsMessage(String messageclass, String viewId)
+  {
+    return JSFunctionExec.getJsMessage(messageclass, viewId, this);
+  }
+
+  @Override
+  public Object getFrameForSource(VamsasSource source)
+  {
+    if (source != null)
+    {
+      if (source instanceof jalview.appletgui.AlignViewport
+              && ((jalview.appletgui.AlignViewport) source).applet.currentAlignFrame.viewport == source)
+      {
+        // should be valid if it just generated an event!
+        return ((jalview.appletgui.AlignViewport) source).applet.currentAlignFrame;
+
+      }
+      // TODO: ensure that if '_af' is specified along with a handler
+      // function, then only events from that alignFrame are sent to that
+      // function
+    }
+    return null;
+  }
+
+  @Override
+  public FeatureRenderer getNewFeatureRenderer(AlignViewportI vp)
+  {
+    return new jalview.appletgui.FeatureRenderer((AlignmentViewport) vp);
+  }
+
+  @Override
+  public String getSelectedSequencesAsAlignment(String format,
+          boolean suffix)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public String getSelectedSequencesAsAlignmentFrom(AlignFrameI alf,
+          String format, boolean suffix)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  // /**
+  // * bind structures in a viewer to any matching sequences in an alignFrame
+  // (use
+  // * sequenceIds to limit scope of search to specific sequences)
+  // *
+  // * @param alFrame
+  // * @param viewer
+  // * @param sequenceIds
+  // * @return TODO: consider making an exception structure for indicating when
+  // * binding fails public SequenceStructureBinding
+  // * addStructureViewInstance( AlignFrame alFrame, Object viewer, String
+  // * sequenceIds) {
+  // *
+  // * if (sequenceIds != null && sequenceIds.length() > 0) { return
+  // * alFrame.addStructureViewInstance(viewer,
+  // * separatorListToArray(sequenceIds)); } else { return
+  // * alFrame.addStructureViewInstance(viewer, null); } // return null; }
+  // */
 }