Refactoring of Jalview, JalviewAppLoader, JalviewApp, various
authorBobHanson <hansonr@stolaf.edu>
Fri, 5 Jun 2020 05:53:39 +0000 (00:53 -0500)
committerBobHanson <hansonr@stolaf.edu>
Fri, 5 Jun 2020 05:53:39 +0000 (00:53 -0500)
applet-related interfaces

- makes JalviewJSApp the JavaScript interface "app" class
- removes JS interface from Jalview
- removes JalviewAppLoader and associated duplication of classes
- adds JavaScript selection and "oninit" listeners (untested)

23 files changed:
src/jalview/api/JalviewApp.java [deleted file]
src/jalview/api/JalviewJSApp.java [moved from src/jalview/bin/JalviewAppLoader.java with 56% similarity]
src/jalview/appletgui/js/JSFunctionExec.java [moved from src/jalview/javascript/JSFunctionExec.java with 99% similarity]
src/jalview/appletgui/js/JalviewLiteJsApi.java [moved from src/jalview/javascript/JalviewLiteJsApi.java with 99% similarity]
src/jalview/appletgui/js/JsCallBack.java [moved from src/jalview/javascript/JsCallBack.java with 97% similarity]
src/jalview/appletgui/js/JsSelectionSender.java [moved from src/jalview/javascript/JsSelectionSender.java with 99% similarity]
src/jalview/appletgui/js/MouseOverListener.java [moved from src/jalview/javascript/MouseOverListener.java with 99% similarity]
src/jalview/appletgui/js/MouseOverStructureListener.java [moved from src/jalview/javascript/MouseOverStructureListener.java with 99% similarity]
src/jalview/bin/AppletParams.java
src/jalview/bin/ArgsParser.java
src/jalview/bin/Jalview.java
src/jalview/bin/JalviewJS2.java
src/jalview/bin/JalviewJSApi.java
src/jalview/bin/JalviewLite.java
src/jalview/ext/jmol/JalviewJmolBinding.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/Desktop.java
src/jalview/project/Jalview2XML.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/util/Platform.java
src/swingjs/api/JSUtilI.java
unused/JalviewAppLoader.java [new file with mode: 0644]
unused/JalviewJSApp.java [new file with mode: 0644]

diff --git a/src/jalview/api/JalviewApp.java b/src/jalview/api/JalviewApp.java
deleted file mode 100644 (file)
index e488d6e..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-package jalview.api;
-
-import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.io.DataSourceType;
-import jalview.io.NewickFile;
-import jalview.javascript.JSFunctionExec;
-import jalview.javascript.MouseOverStructureListener;
-import jalview.structure.SelectionSource;
-import jalview.structure.VamsasSource;
-
-//import java.applet.AppletContext;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import netscape.javascript.JSObject;
-
-public interface JalviewApp
-{
-  public String getParameter(String name);
-
-  public boolean getDefaultParameter(String name, boolean def);
-
-  public URL getDocumentBase();
-
-  public URL getCodeBase();
-
-  public void setAlignPdbStructures(boolean defaultParameter);
-
-  public void newStructureView(PDBEntry pdb, SequenceI[] seqs,
-          String[] chains, DataSourceType protocol);
-
-  public void alignedStructureView(PDBEntry[] pdb, SequenceI[][] seqs,
-          String[][] chains, String[] protocols);
-
-  public void updateForAnnotations();
-
-  public AlignViewportI getViewport();
-
-  public void setFeatureGroupState(String[] groups, boolean state);
-
-  public boolean parseFeaturesFile(String param, DataSourceType protocol);
-
-  public void newFeatureSettings();
-
-  public boolean loadScoreFile(String sScoreFile) throws IOException;
-
-  public void loadTree(NewickFile fin, String treeFile) throws IOException;
-
-  public Vector<Runnable> getJsExecQueue(JSFunctionExec jsFunctionExec);
-
-// deprecated  public AppletContext getAppletContext();
-
-  public boolean isJsfallbackEnabled();
-
-  public JSObject getJSObject();
-
-  public StructureSelectionManagerProvider getStructureSelectionManagerProvider();
-
-  public void updateColoursFromMouseOver(Object source,
-          MouseOverStructureListener mouseOverStructureListener);
-
-  public Object[] getSelectionForListener(SequenceGroup seqsel, ColumnSelection colsel,
-          HiddenColumns hidden, SelectionSource source, Object alignFrame);
-
-  public String arrayToSeparatorList(String[] array);
-
-  public Hashtable<String, int[]> getJSHashes();
-
-  Hashtable<String, Hashtable<String, String[]>> getJSMessages();
-
-  public Object getFrameForSource(VamsasSource source);
-
-  public jalview.renderer.seqfeatures.FeatureRenderer getNewFeatureRenderer(
-          AlignViewportI vp);
-
-}
similarity index 56%
rename from src/jalview/bin/JalviewAppLoader.java
rename to src/jalview/api/JalviewJSApp.java
index 1cdeaec..693ea63 100644 (file)
@@ -1,7 +1,18 @@
-package jalview.bin;
+package jalview.api;
 
-import jalview.api.JalviewApp;
-import jalview.api.StructureSelectionManagerProvider;
+import java.awt.EventQueue;
+//import java.applet.AppletContext;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import jalview.bin.ArgsParser;
+import jalview.bin.Jalview;
+import jalview.bin.JalviewJSApi;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
@@ -13,7 +24,10 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.gui.AlignViewport;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.CalculationChooser;
 import jalview.gui.Desktop;
+import jalview.gui.StructureViewer;
 import jalview.io.AnnotationFile;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
@@ -25,57 +39,49 @@ import jalview.io.IdentifyFile;
 import jalview.io.JPredFile;
 import jalview.io.JnetAnnotationMaker;
 import jalview.io.NewickFile;
+import jalview.renderer.seqfeatures.FeatureRenderer;
+import jalview.structure.SelectionListener;
 import jalview.structure.SelectionSource;
 import jalview.structure.StructureSelectionManager;
+import jalview.structure.VamsasSource;
 import jalview.util.HttpUtils;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 
-import java.awt.EventQueue;
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringTokenizer;
-import java.util.Vector;
+//import netscape.javascript.JSObject;
 
 /**
- * A class to load parameters for either JalviewLite or Jalview
+ * Basically the JalviewLite application, but without JalviewLite
  * 
  * @author hansonr
  *
  */
-public class JalviewAppLoader
+public class JalviewJSApp implements JalviewJSApi
 {
+  private ArgsParser aparser;
 
-  private JalviewApp app; // Jalview or JalviewJS or JalviewLite
+  private String j2sAppletID;
 
   private boolean debug;
 
-  String separator = "\u00AC"; // JalviewLite note: the default used to
+  private String[] ret = new String[1];
+
+  private String separator = "\u00AC"; // JalviewLite note: the default used to
                                        // be '|', but many sequence IDS include
                                        // pipes.
 
-  public String getSeparator()
-  {
-    return separator;
-  }
-
-  public void setSeparator(String separator)
+  public JalviewJSApp(ArgsParser aparser)
   {
-    this.separator = separator;
+    this.aparser = aparser;
+    this.j2sAppletID = (String) aparser.getAppletValue("j2sAppletID",
+            "Jalview", true);
+    Platform.setAppClass(this);
   }
 
-  public JalviewAppLoader(boolean debug)
-  {
-    this.debug = debug;
-  }
 
-  public void load(JalviewApp app)
+  public void load(AlignFrame af)
   {
-
-    this.app = app;
-
-    String sep = app.getParameter("separator");
+    String sep = (String) getAppletParameter("separator", true);
     if (sep != null)
     {
       if (sep.length() > 0)
@@ -89,773 +95,1385 @@ public class JalviewAppLoader
       }
     }
 
-    loadTree();
+    loadTree(af);
     loadScoreFile();
-    loadFeatures();
-    loadAnnotations();
-    loadJnetFile();
-    loadPdbFiles();
-    callInitCallback();
+    loadFeatures(af);
+    loadAnnotations(af);
+    loadJnetFile(af);
+    loadPdbFiles(af);
+  }
+
+  public String getAppID(String frameType)
+  {
+    return j2sAppletID + (frameType == null ? "" : "-" + frameType);
+  }
+
+  // TODO BH 2019
+  //
+  // These are methods that are in JalviewLite that various classes call
+  // but are not in JalviewLiteJsApi. Or, even if they are, other classes
+  // call
+  // them to JalviewLite directly. Some may not be necessary, but they have
+  // to
+  // be at least mentioned here, or the classes calling them should
+  // reference
+  // JalviewLite itself.
+
+  // private boolean alignPDBStructures; // From JalviewLite; not implemented
+  //
+  private Hashtable<String, Hashtable<String, String[]>> jsmessages;
+
+  private Hashtable<String, int[]> jshashes;
+
+  @Override
+  public String getParameter(String name)
+  {
+    return (String) getAppletParameter(name, true);
+  }
+
+  @Override
+  public Object getAppletParameter(String name, boolean asString)
+  {
+    return aparser.getAppletValue(name, null, asString);
   }
 
   /**
-   * Load PDBFiles if any specified by parameter(s). Returns true if loaded,
-   * else false.
-   * 
-   * @param loaderFrame
-   * @return
+   * Get the applet-like code base even though this is an application.
    */
-  protected boolean loadPdbFiles()
+
+  @Override
+  public URL getCodeBase()
   {
-    boolean result = false;
-    /*
-     * <param name="alignpdbfiles" value="false/true"/> Undocumented for 2.6 -
-     * related to JAL-434
-     */
+    return Platform.getCodeBase();
+  }
 
-    boolean doAlign = app.getDefaultParameter("alignpdbfiles", false);
-    app.setAlignPdbStructures(doAlign);
-    /*
-     * <param name="PDBfile" value="1gaq.txt PDB|1GAQ|1GAQ|A PDB|1GAQ|1GAQ|B
-     * PDB|1GAQ|1GAQ|C">
-     * 
-     * <param name="PDBfile2" value="1gaq.txt A=SEQA B=SEQB C=SEQB">
-     * 
-     * <param name="PDBfile3" value="1q0o Q45135_9MICO">
-     */
+  /**
+   * Get the applet-like document base even though this is an application.
+   */
 
-    // Accumulate pdbs here if they are heading for the same view (if
-    // alignPdbStructures is true)
-    Vector<Object[]> pdbs = new Vector<>();
-    // create a lazy matcher if we're asked to
-    jalview.analysis.SequenceIdMatcher matcher = (app
-            .getDefaultParameter("relaxedidmatch", false))
-                    ? new jalview.analysis.SequenceIdMatcher(
-                            app.getViewport().getAlignment()
-                                    .getSequencesArray())
-                    : null;
+  @Override
+  public URL getDocumentBase()
+  {
+    return Platform.getDocumentBase();
+  }
 
-    int pdbFileCount = 0;
-    String param;
-    do
+  @Override
+  public Object getFrameForSource(VamsasSource source)
+  {
+    if (source != null)
     {
-      if (pdbFileCount > 0)
-      {
-        param = app.getParameter("PDBFILE" + pdbFileCount);
-      }
-      else
+      AlignFrame af;
+      if (source instanceof jalview.gui.AlignViewport
+              && source == (af = Jalview.getCurrentAlignFrame())
+                      .getViewport())
       {
-        param = app.getParameter("PDBFILE");
+        // should be valid if it just generated an event!
+        return af;
       }
+      // 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;
+  }
 
-      if (param != null)
-      {
-        PDBEntry pdb = new PDBEntry();
+  @Override
+  public Hashtable<String, int[]> getJSHashes()
+  {
+    return (jshashes == null ? (jshashes = new Hashtable<>()) : jshashes);
+  }
 
-        String seqstring;
-        SequenceI[] seqs = null;
-        String[] chains = null;
+  @Override
+  public Hashtable<String, Hashtable<String, String[]>> getJSMessages()
+  {
+    return (jsmessages == null ? (jsmessages = new Hashtable<>())
+            : jsmessages);
+  }
 
-        StringTokenizer st = new StringTokenizer(param, " ");
+  @Override
+  public Object getJSObject()
+  {
+    return Jalview.getInstance();
+  }
 
-        if (st.countTokens() < 2)
-        {
-          String sequence = app.getParameter("PDBSEQ");
-          if (sequence != null)
-          {
-            seqs = new SequenceI[] { matcher == null
-                    ? (Sequence) app.getViewport().getAlignment()
-                            .findName(sequence)
-                    : matcher.findIdMatch(sequence) };
-          }
+  @Override
+  public FeatureRenderer getNewFeatureRenderer(AlignViewportI vp)
+  {
+    return new jalview.gui.FeatureRenderer((AlignmentPanel) vp);
+  }
 
-        }
-        else
-        {
-          param = st.nextToken();
-          List<SequenceI> tmp = new ArrayList<>();
-          List<String> tmp2 = new ArrayList<>();
+  @Override
+  public Object[] getSelectionForListener(SequenceGroup seqsel,
+          ColumnSelection colsel, HiddenColumns hidden,
+          SelectionSource source, Object alignFrame)
+  {
+    return getSelectionForListener(null, seqsel, colsel, hidden, source,
+            alignFrame);
+  }
 
-          while (st.hasMoreTokens())
-          {
-            seqstring = st.nextToken();
-            StringTokenizer st2 = new StringTokenizer(seqstring, "=");
-            if (st2.countTokens() > 1)
-            {
-              // This is the chain
-              tmp2.add(st2.nextToken());
-              seqstring = st2.nextToken();
-            }
-            tmp.add(matcher == null
-                    ? (Sequence) app.getViewport().getAlignment()
-                            .findName(seqstring)
-                    : matcher.findIdMatch(seqstring));
-          }
+  /**
+   * scorefile
+   * 
+   */
 
-          seqs = tmp.toArray(new SequenceI[tmp.size()]);
-          if (tmp2.size() == tmp.size())
-          {
-            chains = tmp2.toArray(new String[tmp2.size()]);
-          }
-        }
-        pdb.setId(param);
-        ret[0] = param;
-        DataSourceType protocol = resolveFileProtocol(app, ret);
-        // TODO check JAL-357 for files in a jar (CLASSLOADER)
-        pdb.setFile(ret[0]);
+  @Override
+  public boolean loadScoreFile(String sScoreFile) throws IOException
+  {
+    return loadScoreFile(null, sScoreFile);
+  }
+  
+  public boolean loadScoreFile(AlignFrame af, String sScoreFile) throws IOException
+  {
+    (af == null ? Jalview.getCurrentAlignFrame() : af).loadJalviewDataFile(sScoreFile, null, null, null);
+    return true;
+  }
 
-        if (seqs != null)
-        {
-          for (int i = 0; i < seqs.length; i++)
-          {
-            if (seqs[i] != null)
-            {
-              ((Sequence) seqs[i]).addPDBId(pdb);
-              StructureSelectionManager
-                      .getStructureSelectionManager(
-                              (StructureSelectionManagerProvider) app)
-                      .registerPDBEntry(pdb);
-            }
-            else
-            {
-              if (debug)
-              {
-                // this may not really be a problem but we give a warning
-                // anyway
-                System.err.println(
-                        "Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence "
-                                + i + ")");
-              }
-            }
-          }
+  public void loadTree(AlignFrame af, NewickFile nf, String treeFile) throws IOException
+  {
+    if (af == null)
+      af = Jalview.getCurrentAlignFrame();
+    af.getViewport()
+            .setCurrentTree(af.showNewickTree(nf, treeFile).getTree());
+  }
 
-          if (doAlign)
-          {
-            pdbs.addElement(new Object[] { pdb, seqs, chains, protocol });
-          }
-          else
-          {
-            app.newStructureView(pdb, seqs, chains, protocol);
-          }
-        }
-      }
+  @Override
+  public void newFeatureSettings()
+  {
+    System.err.println(
+            "Jalview applet interface newFeatureSettings not implemented");
+  }
 
-      pdbFileCount++;
-    } while (param != null || pdbFileCount < 10);
-    if (pdbs.size() > 0)
-    {
-      SequenceI[][] seqs = new SequenceI[pdbs.size()][];
-      PDBEntry[] pdb = new PDBEntry[pdbs.size()];
-      String[][] chains = new String[pdbs.size()][];
-      String[] protocols = new String[pdbs.size()];
-      for (int pdbsi = 0, pdbsiSize = pdbs
-              .size(); pdbsi < pdbsiSize; pdbsi++)
-      {
-        Object[] o = pdbs.elementAt(pdbsi);
-        pdb[pdbsi] = (PDBEntry) o[0];
-        seqs[pdbsi] = (SequenceI[]) o[1];
-        chains[pdbsi] = (String[]) o[2];
-        protocols[pdbsi] = (String) o[3];
-      }
-      app.alignedStructureView(pdb, seqs, chains, protocols);
-      result = true;
-    }
-    return result;
+  //
+  //
+  // public void setAlignPdbStructures(boolean defaultParameter)
+  // {
+  // alignPDBStructures = true;
+  // }
+  //
+
+  @Override
+  public void newStructureView(PDBEntry pdb, SequenceI[] seqs,
+          String[] chains, DataSourceType protocol)
+  {
+    newStructureView(null, pdb, seqs, chains, protocol);
+    
   }
 
-  /**
-   * Load in a Jnetfile if specified by parameter. Returns true if loaded, else
-   * false.
-   * 
-   * @param alignFrame
-   * @return
-   */
-  protected boolean loadJnetFile()
+  public void newStructureView(AlignFrame af, PDBEntry pdb,
+          SequenceI[] seqs, String[] chains, DataSourceType protocol)
   {
-    boolean result = false;
-    String param = app.getParameter("jnetfile");
-    if (param == null)
-    {
-      // jnet became jpred around 2016
-      param = app.getParameter("jpredfile");
-    }
-    if (param != null)
-    {
-      try
-      {
-        ret[0] = param;
-        DataSourceType protocol = resolveFileProtocol(app, ret);
-        JPredFile predictions = new JPredFile(ret[0], protocol);
-        JnetAnnotationMaker.add_annotation(predictions,
-                app.getViewport().getAlignment(), 0, false);
-        // false == do not add sequence profile from concise output
-        app.getViewport().getAlignment().setupJPredAlignment();
-        app.updateForAnnotations();
-        result = true;
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
-      }
-    }
-    return result;
+    StructureViewer.launchStructureViewer(
+            (af == null ? Jalview.getCurrentAlignFrame() : af).alignPanel,
+            pdb, seqs);
   }
 
   /**
-   * Load annotations if specified by parameter. Returns true if loaded, else
-   * false.
+   * features
+   * @param af 
    * 
-   * @param alignFrame
-   * @return
    */
-  protected boolean loadAnnotations()
+
+  @Override
+  public boolean parseFeaturesFile(String filename, DataSourceType protocol)
   {
-    boolean result = false;
-    String param = app.getParameter("annotations");
-    if (param != null)
-    {
-      ret[0] = param;
-      DataSourceType protocol = resolveFileProtocol(app, ret);
-      param = ret[0];
-      if (new AnnotationFile().annotateAlignmentView(app.getViewport(),
-              param, protocol))
-      {
-        app.updateForAnnotations();
-        result = true;
-      }
-      else
-      {
-        System.err
-                .println("Annotations were not added from annotation file '"
-                        + param + "'");
-      }
-    }
-    return result;
+    return parseFeaturesFile(null, filename, protocol);
+  }
+  
+  public boolean parseFeaturesFile(AlignFrame af, String filename, DataSourceType protocol)
+  {
+    return af.parseFeaturesFile(filename, protocol);
   }
 
+  @Override
+  public void setFeatureGroupState(String[] groups, boolean state)
+  {
+    setFeatureGroupState(null, groups, state);
+  }
+
+  public void setFeatureGroupState(AlignFrame af, String[] groups, boolean state) {
+    (af == null ? Jalview.getCurrentAlignFrame() : af).setFeatureGroupState(groups, state);
+  }
   /**
-   * Load features file and view settings as specified by parameters. Returns
-   * true if features were loaded, else false.
+   * annotations, jpredfile, jnetfile
    * 
-   * @param alignFrame
-   * @return
    */
-  protected boolean loadFeatures()
+
+  @Override
+  public void updateForAnnotations()
   {
-    boolean result = false;
-    // ///////////////////////////
-    // modify display of features
-    // we do this before any features have been loaded, ensuring any hidden
-    // groups are hidden when features first displayed
-    //
-    // hide specific groups
-    //
-    String param = app.getParameter("hidefeaturegroups");
-    if (param != null)
-    {
-      app.setFeatureGroupState(separatorListToArray(param, separator),
-              false);
-      // app.setFeatureGroupStateOn(newAlignFrame, param, false);
-    }
-    // show specific groups
-    param = app.getParameter("showfeaturegroups");
-    if (param != null)
-    {
-      app.setFeatureGroupState(separatorListToArray(param, separator),
-              true);
-      // app.setFeatureGroupStateOn(newAlignFrame, param, true);
-    }
-    // and now load features
-    param = app.getParameter("features");
-    if (param != null)
-    {
-      ret[0] = param;
-      DataSourceType protocol = resolveFileProtocol(app, ret);
-
-      result = app.parseFeaturesFile(ret[0], protocol);
-    }
-
-    param = app.getParameter("showFeatureSettings");
-    if (param != null && param.equalsIgnoreCase("true"))
-    {
-      app.newFeatureSettings();
-    }
-    return result;
+    updateForAnnotations(null);
   }
 
-  /**
-   * Load a score file if specified by parameter. Returns true if file was
-   * loaded, else false.
-   * 
-   * @param loaderFrame
-   */
-  protected boolean loadScoreFile()
+  public void updateForAnnotations(AlignFrame af)
   {
-    boolean result = false;
-    String sScoreFile = app.getParameter("scoreFile");
-    if (sScoreFile != null && !"".equals(sScoreFile))
-    {
-      try
-      {
-        if (debug)
-        {
-          System.err.println(
-                  "Attempting to load T-COFFEE score file from the scoreFile parameter");
-        }
-        result = app.loadScoreFile(sScoreFile);
-        if (!result)
-        {
-          System.err.println(
-                  "Failed to parse T-COFFEE parameter as a valid score file ('"
-                          + sScoreFile + "')");
-        }
-      } catch (Exception e)
-      {
-        System.err.printf("Cannot read score file: '%s'. Cause: %s \n",
-                sScoreFile, e.getMessage());
-      }
-    }
-    return result;
+    (af == null ? Jalview.getCurrentAlignFrame() : af).updateForAnnotations();
   }
 
-  String[] ret = new String[1];
-
-  /**
-   * Load a tree for the alignment if specified by parameter. Returns true if a
-   * tree was loaded, else false.
-   * 
-   * @param loaderFrame
-   * @return
-   */
-  protected boolean loadTree()
+  @Override
+  public boolean addPdbFile(AlignFrame alf, String sequenceId,
+          String pdbEntryString, String pdbFile)
   {
-    boolean result = false;
-    String treeFile = app.getParameter("tree");
-    if (treeFile == null)
+    if (alf == null)
     {
-      treeFile = app.getParameter("treeFile");
+      alf = Jalview.getCurrentAlignFrame();
     }
-
-    if (treeFile != null)
+    SequenceI toaddpdb = alf.getViewport().getAlignment()
+            .findName(sequenceId);
+    boolean needtoadd = false;
+    if (toaddpdb != null)
     {
-      try
+      Vector<PDBEntry> pdbe = toaddpdb.getAllPDBEntries();
+      PDBEntry pdbentry = null;
+      if (pdbe != null && pdbe.size() > 0)
       {
-        ret[0] = treeFile;
-        NewickFile fin = new NewickFile(treeFile,
-                resolveFileProtocol(app, ret));
-        fin.parse();
-
-        if (fin.getTree() != null)
+        for (int pe = 0, peSize = pdbe.size(); pe < peSize; pe++)
         {
-          app.loadTree(fin, ret[0]);
-          result = true;
-          if (debug)
+          pdbentry = pdbe.elementAt(pe);
+          if (!pdbentry.getId().equals(pdbEntryString)
+                  && !pdbentry.getFile().equals(pdbFile))
           {
-            System.out.println("Successfully imported tree.");
+            pdbentry = null;
           }
-        }
-        else
-        {
-          if (debug)
+          else
           {
-            System.out.println(
-                    "Tree parameter did not resolve to a valid tree.");
+            continue;
           }
         }
-      } catch (Exception ex)
+      }
+      if (pdbentry == null)
       {
-        ex.printStackTrace();
+        pdbentry = new PDBEntry();
+        pdbentry.setId(pdbEntryString);
+        pdbentry.setFile(pdbFile);
+        needtoadd = true; // add this new entry to sequence.
+      }
+      // resolve data source
+      // TODO: this code should be a refactored to an io package
+      DataSourceType protocol = AppletFormatAdapter.resolveProtocol(pdbFile,
+              FileFormat.PDB);
+      if (protocol == null)
+      {
+        return false;
+      }
+      if (needtoadd)
+      {
+        pdbentry.setProperty("protocol", protocol);
+        toaddpdb.addPDBId(pdbentry);
+        alf.alignPanel.getStructureSelectionManager()
+                .registerPDBEntry(pdbentry);
       }
     }
-    return result;
+    return true;
   }
 
-  /**
-   * form a complete URL given a path to a resource and a reference location on
-   * the same server
-   * 
-   * @param targetPath
-   *          - an absolute path on the same server as localref or a document
-   *          located relative to localref
-   * @param localref
-   *          - a URL on the same server as url
-   * @return a complete URL for the resource located by url
-   */
-  public static String resolveUrlForLocalOrAbsolute(String targetPath,
-          URL localref)
+  @Override
+  public String arrayToSeparatorList(String[] array)
   {
-    String resolvedPath = "";
-    if (targetPath.startsWith("/"))
-    {
-      String codebase = localref.toString();
-      String localfile = localref.getFile();
-      resolvedPath = codebase.substring(0,
-              codebase.length() - localfile.length()) + targetPath;
-      return resolvedPath;
-    }
-
-    /*
-     * get URL path and strip off any trailing file e.g.
-     * www.jalview.org/examples/index.html#applets?a=b is trimmed to
-     * www.jalview.org/examples/
-     */
-    String urlPath = localref.toString();
-    String directoryPath = urlPath;
-    int lastSeparator = directoryPath.lastIndexOf("/");
-    if (lastSeparator > 0)
-    {
-      directoryPath = directoryPath.substring(0, lastSeparator + 1);
-    }
-
-    if (targetPath.startsWith("/"))
-    {
-      /*
-       * construct absolute URL to a file on the server - this is not allowed?
-       */
-      // String localfile = localref.getFile();
-      // resolvedPath = urlPath.substring(0,
-      // urlPath.length() - localfile.length())
-      // + targetPath;
-      resolvedPath = directoryPath + targetPath.substring(1);
-    }
-    else
-    {
-      resolvedPath = directoryPath + targetPath;
-    }
-    // if (debug)
-    // {
-    // System.err.println(
-    // "resolveUrlForLocalOrAbsolute returning " + resolvedPath);
-    // }
-    return resolvedPath;
+    return arrayToSeparatorList(array, separator);
   }
 
   /**
-   * parse the string into a list
+   * concatenate the list with separator
    * 
    * @param list
    * @param separator
-   * @return elements separated by separator
+   * @return concatenated string
    */
-  public static String[] separatorListToArray(String list, String separator)
+  public static String arrayToSeparatorList(String[] list, String separator)
   {
-    // TODO use StringUtils version (slightly different...)
-    int seplen = separator.length();
-    if (list == null || list.equals("") || list.equals(separator))
-    {
-      return null;
-    }
-    Vector<String> jv = new Vector<>();
-    int cp = 0, pos;
-    while ((pos = list.indexOf(separator, cp)) > cp)
-    {
-      jv.addElement(list.substring(cp, pos));
-      cp = pos + seplen;
-    }
-    if (cp < list.length())
-    {
-      String c = list.substring(cp);
-      if (!c.equals(separator))
-      {
-        jv.addElement(c);
-      }
-    }
-    if (jv.size() > 0)
+    // TODO use StringUtils version
+    StringBuffer v = new StringBuffer();
+    if (list != null && list.length > 0)
     {
-      String[] v = new String[jv.size()];
-      for (int i = 0; i < v.length; i++)
+      for (int i = 0, iSize = list.length; i < iSize; i++)
       {
-        v[i] = jv.elementAt(i);
+        if (list[i] != null)
+        {
+          if (i > 0)
+          {
+            v.append(separator);
+          }
+          v.append(list[i]);
+        }
       }
-      jv.removeAllElements();
       // if (debug)
       // {
-      // System.err.println("Array from '" + separator
-      // + "' separated List:\n" + v.length);
-      // for (int i = 0; i < v.length; i++)
-      // {
-      // System.err.println("item " + i + " '" + v[i] + "'");
-      // }
+      // System.err
+      // .println("Returning '" + separator + "' separated List:\n");
+      // System.err.println(v);
       // }
-      return v;
+      return v.toString();
     }
     // if (debug)
     // {
     // System.err.println(
-    // "Empty Array from '" + separator + "' separated List");
+    // "Returning empty '" + separator + "' separated List\n");
     // }
-    return null;
+    return "" + separator;
   }
 
-  public static DataSourceType resolveFileProtocol(JalviewApp app,
-          String[] retPath)
+  @Override
+  public String getAlignment(String format)
   {
-    String path = retPath[0];
-    /*
-     * is it paste data?
-     */
-    if (path.startsWith("PASTE"))
-    {
-      retPath[0] = path.substring(5);
-      return DataSourceType.PASTE;
-    }
+    return getAlignmentFrom(null, format, null);
+  }
 
-    /*
-     * is it a URL?
-     */
-    if (path.indexOf("://") >= 0)
-    {
-      return DataSourceType.URL;
-    }
+  @Override
+  public String getAlignment(String format, String suffix)
+  {
+    return getAlignmentFrom(Jalview.getCurrentAlignFrame(), format, suffix);
+  }
 
-    /*
-     * try relative to document root
-     */
-    URL documentBase = app.getDocumentBase();
-    String withDocBase = resolveUrlForLocalOrAbsolute(path, documentBase);
-    if (HttpUtils.isValidUrl(withDocBase))
-    {
-      // if (debug)
-      // {
-      // System.err.println("Prepended document base '" + documentBase
-      // + "' to make: '" + withDocBase + "'");
-      // }
-      retPath[0] = withDocBase;
-      return DataSourceType.URL;
+  @Override
+  public String getAlignmentFrom(AlignFrame alf, String format)
+  {
+    return getAlignmentFrom(alf, format, null);
+  }
+
+  @Override
+  public String getAlignmentFrom(AlignFrame alf, String format,
+          String suffix)
+  {
+    try
+    {
+      if (alf == null)
+      {
+        alf = Jalview.getCurrentAlignFrame();
+      }
+      boolean seqlimits = (suffix == null
+              || suffix.equalsIgnoreCase("true"));
+
+      FileFormatI theFormat = FileFormats.getInstance().forName(format);
+      String reply = new AppletFormatAdapter().formatSequences(theFormat,
+              alf.getViewport().getAlignment(), seqlimits);
+      return reply;
+    } catch (IllegalArgumentException ex)
+    {
+      ex.printStackTrace();
+      return "Error retrieving alignment, possibly invalid format specifier: "
+              + format;
     }
+  }
 
-    /*
-     * try relative to codebase (if different to document base)
-     */
-    URL codeBase = app.getCodeBase();
-    String withCodeBase = resolveUrlForLocalOrAbsolute(path, codeBase);
-    if (!withCodeBase.equals(withDocBase)
-            && HttpUtils.isValidUrl(withCodeBase))
+  @Override
+  public String getAlignmentOrder()
+  {
+    return getAlignmentFrom(Jalview.getCurrentAlignFrame(), null);
+  }
+
+  @Override
+  public String getAlignmentOrderFrom(AlignFrame alf)
+  {
+    return getAlignmentFrom(alf, null);
+  }
+
+  @Override
+  public String getAlignmentOrderFrom(AlignFrame alf, String sep)
+  {
+    if (alf == null)
     {
-      // if (debug)
-      // {
-      // System.err.println("Prepended codebase '" + codeBase
-      // + "' to make: '" + withCodeBase + "'");
-      // }
-      retPath[0] = withCodeBase;
-      return DataSourceType.URL;
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    AlignmentI alorder = alf.getViewport().getAlignment();
+    String[] order = new String[alorder.getHeight()];
+    for (int i = 0; i < order.length; i++)
+    {
+      order[i] = alorder.getSequenceAt(i).getName();
     }
+    return arrayToSeparatorList(order, sep);
+  }
 
-    /*
-     * try locating by classloader; try this last so files in the directory
-     * are resolved using document base
-     */
-    if (inArchive(app.getClass(), path))
+  @Override
+  public String getAnnotation()
+  {
+    return getAnnotationFrom(null);
+  }
+
+  @Override
+  public String getAnnotationFrom(AlignFrame alf)
+  {
+    if (alf == null)
     {
-      return DataSourceType.CLASSLOADER;
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    String annotation = new AnnotationFile()
+            .printAnnotationsForView(alf.getViewport());
+    return annotation;
+  }
+
+  @Override
+  public String getFeatureGroups()
+  {
+    return getFeatureGroupsOn(null);
+  }
+
+  @Override
+  public String getFeatureGroupsOfState(boolean visible)
+  {
+    return getFeatureGroupsOfStateOn(null, visible);
+  }
+
+  @Override
+  public String getFeatureGroupsOfStateOn(AlignFrame alf, boolean visible)
+  {
+    if (alf == null)
+    {
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    return arrayToSeparatorList(alf.getFeatureGroupsOfState(visible));
+  }
+
+  @Override
+  public String getFeatureGroupsOn(AlignFrame alf)
+  {
+    if (alf == null)
+    {
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    return arrayToSeparatorList(alf.getFeatureGroups());
+  }
+
+  @Override
+  public String getFeatures(String format)
+  {
+    return getFeaturesFrom(null, format);
+  }
+
+  /**
+   * JavaScript interface to print the alignment frame
+   * 
+   * @param alf
+   * @param format
+   *          "jalview" or "gff" with or without ";includeComplement" or
+   *          ";includeNonpositional"; default with no ";" is
+   *          ";includeNonpositional"
+   * @return
+   */
+  @Override
+  public String getFeaturesFrom(AlignFrame alf, String format)
+  {
+    if (alf == null)
+    {
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    String features;
+    FeaturesFile formatter = new FeaturesFile();
+    format = format.toLowerCase();
+    if (format.indexOf(";") < 0)
+      format += ";includenonpositional";
+    boolean nonpos = format.indexOf(";includenonpositional") > 0;
+    boolean compl = format.indexOf(";includecomplement") >= 0;
+    if (format.startsWith("jalview"))
+    {
+      features = formatter.printJalviewFormat(
+              alf.getViewport().getAlignment().getSequencesArray(),
+              alf.alignPanel.getFeatureRenderer(), nonpos, compl);
+    }
+    else
+    {
+      features = formatter.printGffFormat(
+              alf.getViewport().getAlignment().getSequencesArray(),
+              alf.alignPanel.getFeatureRenderer(), nonpos, compl);
+    }
+
+    if (features == null)
+    {
+      features = "";
     }
+    return features;
+
+  }
+
+  @Override
+  public String getJsMessage(String messageclass, String viewId)
+  {
+    // TODO Auto-generated method stub
     return null;
   }
 
   /**
-   * Discovers whether the given file is in the Applet Archive
+   * read sequence1...sequenceN as a raw alignment
    * 
-   * @param f
-   *          String
-   * @return boolean
+   * @param jalviewApp
+   * @return
    */
-  private static boolean inArchive(Class<?> c, String f)
+  public String getPastedSequence(JalviewJSApp jalviewApp)
   {
-    // This might throw a security exception in certain browsers
-    // Netscape Communicator for instance.
+    StringBuffer data = new StringBuffer("PASTE");
+    int i = 1;
+    String file = null;
+    while ((file = (String) getAppletParameter("sequence" + i,
+            true)) != null)
+    {
+      data.append(file.toString() + "\n");
+      i++;
+    }
+    if (data.length() > 5)
+    {
+      file = data.toString();
+    }
+    return file;
+  }
+
+  /**
+   * 
+   * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences()
+   */
+  @Override
+  public String getSelectedSequences()
+  {
+    return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame());
+  }
+
+  /**
+   * 
+   * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences(java.lang.String)
+   */
+  @Override
+  public String getSelectedSequences(String sep)
+  {
+    return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame(), sep);
+  }
+
+  @Override
+  public String getSelectedSequencesAsAlignment(String format,
+          String suffix)
+  {
+    return getSelectedSequencesAsAlignmentFrom(null, format, suffix);
+  }
+
+  @Override
+  public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
+          String format, String suffix)
+  {
+
+    if (alf == null)
+    {
+      alf = Jalview.getCurrentAlignFrame();
+    }
+
+    boolean seqlimits = (suffix == null || suffix.equalsIgnoreCase("true"));
     try
     {
-      boolean rtn = (c.getResourceAsStream("/" + f) != null);
-      // if (debug)
-      // {
-      // System.err.println("Resource '" + f + "' was "
-      // + (rtn ? "" : "not ") + "located by classloader.");
-      // }
-      return rtn;
-    } catch (Exception ex)
+      AlignViewport vp = alf.getViewport();
+      FileFormatI theFormat = FileFormats.getInstance().forName(format);
+      if (vp.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(vp.getSelectionAsNewSequence()), seqlimits);
+        return reply;
+      }
+    } catch (IllegalArgumentException ex)
     {
-      System.out.println("Exception checking resources: " + f + " " + ex);
-      return false;
+      ex.printStackTrace();
+      return "Error retrieving alignment, possibly invalid format specifier: "
+              + format;
+    }
+    return "";
+  }
+
+  /**
+   * 
+   * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
+   *      .AlignFrame)
+   */
+  @Override
+  public String getSelectedSequencesFrom(AlignFrame alf)
+  {
+    return getSelectedSequencesFrom(alf, null);
+  }
+
+  @Override
+  public String getSelectedSequencesFrom(AlignFrame alf, String sep)
+  {
+    if (alf == null)
+    {
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    StringBuffer result = new StringBuffer("");
+    if (sep == null || sep.length() == 0)
+    {
+      sep = separator; // "+0x00AC;
+    }
+    AlignViewport v = alf.getViewport();
+    if (v.getSelectionGroup() != null)
+    {
+      SequenceI[] seqs = v.getSelectionGroup()
+              .getSequencesInOrder(v.getAlignment());
+
+      for (int i = 0; i < seqs.length; i++)
+      {
+        result.append(seqs[i].getName());
+        result.append(sep);
+      }
+    }
+
+    return result.toString();
+  }
+
+  public Object[] getSelectionForListener(AlignFrame alf,
+          SequenceGroup seqsel, ColumnSelection colsel,
+          HiddenColumns hidden, SelectionSource source, Object alignFrame)
+  {
+    if (alf == null)
+    {
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    // System.err.println("Testing selection event relay to
+    // jsfunction:"+_listener);
+    String setid = "";
+    AlignFrame src = (AlignFrame) alignFrame;
+    if (source != null)
+    {
+      if (source instanceof AlignViewport && alf.getViewport() == source)
+      {
+        // should be valid if it just generated an event!
+        src = alf;
+
+      }
+    }
+    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 getSeparator()
+  {
+    return separator;
+  }
+
+  /**
+   * 
+   * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
+   *      .AlignFrame, java.lang.String)
+   */
+  @Override
+  public void highlight(String sequenceId, String position,
+          String alignedPosition)
+  {
+    highlightIn(null, sequenceId, position, alignedPosition);
+  }
+
+  @Override
+  public void highlightIn(AlignFrame alf, final String sequenceId,
+          final String position, final String alignedPosition)
+  {
+    if (alf == null)
+    {
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    // TODO: could try to highlight in all alignments if alf==null
+    jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
+            alf.getViewport().getAlignment().getSequencesArray());
+    final SequenceI sq = matcher.findIdMatch(sequenceId);
+    if (sq != null)
+    {
+      int apos = -1;
+      try
+      {
+        apos = Integer.valueOf(position).intValue();
+        apos--;
+      } catch (NumberFormatException ex)
+      {
+        return;
+      }
+      final int pos = apos;
+      // use vamsas listener to broadcast to all listeners in scope
+      if (alignedPosition != null && (alignedPosition.trim().length() == 0
+              || alignedPosition.toLowerCase().indexOf("false") > -1))
+      {
+        java.awt.EventQueue.invokeLater(new Runnable()
+        {
+          @Override
+          public void run()
+          {
+            StructureSelectionManager
+                    .getStructureSelectionManager(Desktop.getInstance())
+                    .mouseOverVamsasSequence(sq, sq.findIndex(pos), null);
+          }
+        });
+      }
+      else
+      {
+        java.awt.EventQueue.invokeLater(new Runnable()
+        {
+          @Override
+          public void run()
+          {
+            StructureSelectionManager
+                    .getStructureSelectionManager(Desktop.getInstance())
+                    .mouseOverVamsasSequence(sq, pos, null);
+          }
+        });
+      }
+    }
+  }
+
+  public AlignFrame loadAlignment(String text, int width, int height,
+          String title)
+  {
+    AlignmentI al = null;
+
+    try
+    {
+      FileFormatI format = new IdentifyFile().identify(text,
+              DataSourceType.PASTE);
+      al = new AppletFormatAdapter().readFile(text, DataSourceType.PASTE,
+              format);
+      if (al.getHeight() > 0)
+      {
+        return new AlignFrame(al, width, height, title);
+      }
+    } catch (IOException ex)
+    {
+      ex.printStackTrace();
+    }
+    return null;
+  }
+
+  // public void setMouseoverListener(String listener)
+  // {
+  // appLoader.setMouseoverListener(listener);
+  // }
+  //
+  //
+  // public void setMouseoverListener(AlignFrame af, String listener)
+  // {
+  // }
+  //
+
+  @Override
+  public AlignFrame loadAlignment(String text, String title)
+  {
+    return loadAlignment(text, AlignFrame.DEFAULT_WIDTH,
+            AlignFrame.DEFAULT_HEIGHT, title);
+  }
+
+  @Override
+  public void loadAnnotation(String annotation)
+  {
+    loadAnnotationFrom(null, annotation);
+  }
+
+  @Override
+  public void loadAnnotationFrom(AlignFrame alf, String annotation)
+  {
+    if (alf == null)
+    {
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    if (new AnnotationFile().annotateAlignmentView(alf.getViewport(),
+            annotation, DataSourceType.PASTE))
+    {
+      alf.alignPanel.fontChanged();
+      alf.alignPanel.setScrollValues(0, 0);
+    }
+    else
+    {
+      alf.parseFeaturesFile(annotation, DataSourceType.PASTE);
+    }
+  }
+
+  /**
+   * Load annotations if specified by parameter. Returns true if loaded, else
+   * false.
+   * 
+   * 
+   * @param alignFrame
+   * @return
+   */
+  protected boolean loadAnnotations(AlignFrame af)
+  {
+    boolean result = false;
+    String param = (String) getAppletParameter("annotations", true);
+    if (param != null)
+    {
+      ret[0] = param;
+      DataSourceType protocol = resolveFileProtocol(ret);
+      param = ret[0];
+      if (new AnnotationFile().annotateAlignmentView(af.getViewport(), param,
+              protocol))
+      {
+        updateForAnnotations();
+        result = true;
+      }
+      else
+      {
+        System.err
+                .println("Annotations were not added from annotation file '"
+                        + param + "'");
+      }
+    }
+    return result;
+  }
+
+  //// JalviewJSApi
+
+  /**
+   * Load features file and view settings as specified by parameters. Returns
+   * true if features were loaded, else false.
+   * @param  
+   * 
+   * @param alignFrame
+   * @return
+   */
+  protected boolean loadFeatures(AlignFrame af)
+  {
+    boolean result = false;
+    // ///////////////////////////
+    // modify display of features
+    // we do this before any features have been loaded, ensuring any hidden
+    // groups are hidden when features first displayed
+    //
+    // hide specific groups
+    //
+    String param = (String) getAppletParameter("hidefeaturegroups", true);
+    if (param != null)
+    {
+      setFeatureGroupState(af, separatorListToArray(param, separator), false);
+      // setFeatureGroupStateOn(newAlignFrame, param, false);
+    }
+    // show specific groups
+    param = (String) getAppletParameter("showfeaturegroups", true);
+    if (param != null)
+    {
+      setFeatureGroupState(af, separatorListToArray(param, separator), true);
+      // setFeatureGroupStateOn(newAlignFrame, param, true);
+    }
+    // and now load features
+    param = (String) getAppletParameter("features", true);
+    if (param != null)
+    {
+      ret[0] = param;
+      DataSourceType protocol = resolveFileProtocol(ret);
+
+      result = parseFeaturesFile(af, ret[0], protocol);
+    }
+
+    param = (String) getAppletParameter("showFeatureSettings", true);
+    if (param != null && param.equalsIgnoreCase("true"))
+    {
+      newFeatureSettings();
+    }
+    return result;
+  }
+
+  @Override
+  public void loadFeatures(String features, boolean autoenabledisplay)
+  {
+    loadFeaturesFrom(null, features, autoenabledisplay);
+  }
+
+  @Override
+  public boolean loadFeaturesFrom(AlignFrame alf, String features,
+          boolean autoenabledisplay)
+  {
+    if (alf == null)
+    {
+      alf = Jalview.getCurrentAlignFrame();
+    }
+    boolean ret = alf.parseFeaturesFile(features, DataSourceType.PASTE);
+    if (!ret)
+    {
+      return false;
+    }
+    if (autoenabledisplay)
+    {
+      alf.getViewport().setShowSequenceFeatures(true);
+      // this next was for a checkbox in JalviewLite
+      // ((AlignFrame) alf).getViewport().sequenceFeatures.setState(true);
+    }
+    return true;
+  }
+
+  /**
+   * Load in a Jnetfile if specified by parameter. Returns true if loaded, else
+   * false.
+   * 
+   * @param alignFrame
+   * @return
+   */
+  protected boolean loadJnetFile(AlignFrame af)
+  {
+    boolean result = false;
+    String param = (String) getAppletParameter("jnetfile", true);
+    if (param == null)
+    {
+      // jnet became jpred around 2016
+      param = (String) getAppletParameter("jpredfile", true);
+    }
+    if (param != null)
+    {
+      try
+      {
+        ret[0] = param;
+        DataSourceType protocol = resolveFileProtocol(ret);
+        JPredFile predictions = new JPredFile(ret[0], protocol);
+        JnetAnnotationMaker.add_annotation(predictions,
+                af.getViewport().getAlignment(), 0, false);
+        // false == do not add sequence profile from concise output
+        af.getViewport().getAlignment().setupJPredAlignment();
+        updateForAnnotations();
+        result = true;
+      } catch (Exception ex)
+      {
+        ex.printStackTrace();
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Load PDBFiles if any specified by parameter(s). Returns true if loaded,
+   * else false.
+   * 
+   * @param loaderFrame
+   * @return
+   */
+  protected boolean loadPdbFiles(AlignFrame af)
+  {
+    boolean result = false;
+    /*
+     * <param name="alignpdbfiles" value="false/true"/> Undocumented for 2.6 -
+     * related to JAL-434
+     */
+
+    // not supported (as for JalviewLite)
+    // boolean doAlign = false;//"true".equalsIgnoreCase("" +
+    // getAppletParameter("alignpdbfiles", false));
+    // setAlignPdbStructures(doAlign);
+    /*
+     * <param name="PDBfile" value="1gaq.txt PDB|1GAQ|1GAQ|A PDB|1GAQ|1GAQ|B
+     * PDB|1GAQ|1GAQ|C">
+     * 
+     * <param name="PDBfile2" value="1gaq.txt A=SEQA B=SEQB C=SEQB">
+     * 
+     * <param name="PDBfile3" value="1q0o Q45135_9MICO">
+     */
+
+    // Accumulate pdbs here if they are heading for the same view (if
+    // alignPdbStructures is true)
+    // ArrayList<Object[]> pdbs = new ArrayList<>();
+    // create a lazy matcher if we're asked to
+    boolean relaxed = "true".equalsIgnoreCase(
+            "" + getAppletParameter("relaxedidmatch", false));
+    jalview.analysis.SequenceIdMatcher matcher = relaxed
+            ? new jalview.analysis.SequenceIdMatcher(
+                    af.getViewport().getAlignment().getSequencesArray())
+            : null;
+
+    int pdbFileCount = 0;
+    String param;
+    do
+    {
+      if (pdbFileCount > 0)
+      {
+        param = (String) getAppletParameter("PDBFILE" + pdbFileCount, true);
+      }
+      else
+      {
+        param = (String) getAppletParameter("PDBFILE", true);
+      }
+
+      if (param != null)
+      {
+        PDBEntry pdb = new PDBEntry();
+
+        String seqstring;
+        SequenceI[] seqs = null;
+        String[] chains = null;
+
+        StringTokenizer st = new StringTokenizer(param, " ");
+
+        if (st.countTokens() < 2)
+        {
+          String sequence = (String) getAppletParameter("PDBSEQ", true);
+          if (sequence != null)
+          {
+            seqs = new SequenceI[] { matcher == null
+                    ? (Sequence) af.getViewport().getAlignment()
+                            .findName(sequence)
+                    : matcher.findIdMatch(sequence) };
+          }
+
+        }
+        else
+        {
+          param = st.nextToken();
+          List<SequenceI> tmp = new ArrayList<>();
+          List<String> tmp2 = new ArrayList<>();
+
+          while (st.hasMoreTokens())
+          {
+            seqstring = st.nextToken();
+            StringTokenizer st2 = new StringTokenizer(seqstring, "=");
+            if (st2.countTokens() > 1)
+            {
+              // This is the chain
+              tmp2.add(st2.nextToken());
+              seqstring = st2.nextToken();
+            }
+            tmp.add(matcher == null
+                    ? (Sequence) af.getViewport().getAlignment()
+                            .findName(seqstring)
+                    : matcher.findIdMatch(seqstring));
+          }
+
+          seqs = tmp.toArray(new SequenceI[tmp.size()]);
+          if (tmp2.size() == tmp.size())
+          {
+            chains = tmp2.toArray(new String[tmp2.size()]);
+          }
+        }
+        pdb.setId(param);
+        ret[0] = param;
+        DataSourceType protocol = resolveFileProtocol(ret);
+        // TODO check JAL-357 for files in a jar (CLASSLOADER)
+        pdb.setFile(ret[0]);
+
+        if (seqs != null)
+        {
+          for (int i = 0; i < seqs.length; i++)
+          {
+            if (seqs[i] != null)
+            {
+              ((Sequence) seqs[i]).addPDBId(pdb);
+              StructureSelectionManager
+                      .getStructureSelectionManager(
+                              (StructureSelectionManagerProvider) this)
+                      .registerPDBEntry(pdb);
+            }
+            else
+            {
+              if (debug)
+              {
+                // this may not really be a problem but we give a warning
+                // anyway
+                System.err.println(
+                        "Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence "
+                                + i + ")");
+              }
+            }
+          }
+
+          // if (doAlign)
+          // {
+          // pdbs.add(new Object[] { pdb, seqs, chains, protocol });
+          // }
+          // else
+          {
+            newStructureView(af, pdb, seqs, chains, protocol);
+          }
+        }
+      }
+
+      pdbFileCount++;
+    } while (param != null || pdbFileCount < 10);
+    //
+    // if (doAlign && pdbs.size() > 0)
+    // {
+    // SequenceI[][] seqs = new SequenceI[pdbs.size()][];
+    // PDBEntry[] pdb = new PDBEntry[pdbs.size()];
+    // String[][] chains = new String[pdbs.size()][];
+    // String[] protocols = new String[pdbs.size()];
+    // for (int pdbsi = 0, pdbsiSize = pdbs
+    // .size(); pdbsi < pdbsiSize; pdbsi++)
+    // {
+    // Object[] o = pdbs.get(pdbsi);
+    // pdb[pdbsi] = (PDBEntry) o[0];
+    // seqs[pdbsi] = (SequenceI[]) o[1];
+    // chains[pdbsi] = (String[]) o[2];
+    // protocols[pdbsi] = (String) o[3];
+    // }
+    //// alignedStructureView(pdb, seqs, chains, protocols);
+    // result = true;
+    // }
+    return result;
+  }
+
+  /**
+   * Load a score file if specified by parameter. Returns true if file was
+   * loaded, else false.
+   * 
+   * @param loaderFrame
+   */
+  protected boolean loadScoreFile()
+  {
+    boolean result = false;
+    String sScoreFile = (String) getAppletParameter("scoreFile", true);
+    if (sScoreFile != null && !"".equals(sScoreFile))
+    {
+      try
+      {
+        if (debug)
+        {
+          System.err.println(
+                  "Attempting to load T-COFFEE score file from the scoreFile parameter");
+        }
+        result = loadScoreFile(sScoreFile);
+        if (!result)
+        {
+          System.err.println(
+                  "Failed to parse T-COFFEE parameter as a valid score file ('"
+                          + sScoreFile + "')");
+        }
+      } catch (Exception e)
+      {
+        System.err.printf("Cannot read score file: '%s'. Cause: %s \n",
+                sScoreFile, e.getMessage());
+      }
     }
+    return result;
   }
 
-  public void callInitCallback()
+  /**
+   * Load a tree for the alignment if specified by parameter. Returns true if a
+   * tree was loaded, else false.
+   * 
+   * @return
+   */
+  protected boolean loadTree(AlignFrame af)
   {
-    String initjscallback = app.getParameter("oninit");
-    if (initjscallback == null)
+    boolean result = false;
+    String treeFile = (String) getAppletParameter("tree", true);
+    if (treeFile == null)
     {
-      return;
+      treeFile = (String) getAppletParameter("treefile", true);
     }
-    initjscallback = initjscallback.trim();
-    if (initjscallback.length() > 0)
+
+    if (treeFile != null)
     {
-      // TODO
+      try
+      {
+        ret[0] = treeFile;
+        NewickFile fin = new NewickFile(treeFile, resolveFileProtocol(ret));
+        fin.parse();
+
+        if (fin.getTree() != null)
+        {
+          loadTree(af, fin, ret[0]);
+          result = true;
+          if (debug)
+          {
+            System.out.println("Successfully imported tree.");
+          }
+        }
+        else
+        {
+          if (debug)
+          {
+            System.out.println(
+                    "Tree parameter did not resolve to a valid tree.");
+          }
+        }
+      } catch (Exception ex)
+      {
+        ex.printStackTrace();
+      }
     }
+    return result;
   }
 
   /**
-   * read sequence1...sequenceN as a raw alignment
+   * public static method for JalviewJS API to open a PCAPanel without
+   * necessarily using a dialog.
    * 
-   * @param jalviewApp
-   * @return
+   * @param af
+   * @param modelName
+   * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences"
+   *         if number of sequences selected is inappropriate
    */
-  public String getPastedSequence(JalviewApp jalviewApp)
+  @Override
+  public Object openPcaPanel(AlignFrame af, String modelName)
   {
-    StringBuffer data = new StringBuffer("PASTE");
-    int i = 1;
-    String file = null;
-    while ((file = app.getParameter("sequence" + i)) != null)
+    if (af == null)
     {
-      data.append(file.toString() + "\n");
-      i++;
-    }
-    if (data.length() > 5)
-    {
-      file = data.toString();
+      af = Jalview.getCurrentAlignFrame();
     }
-    return file;
+    return CalculationChooser.openPcaPanel(af, modelName, null);
   }
 
   /**
-   * concatenate the list with separator
+   * Open a new Tree panel on the desktop statically. Params are standard (not
+   * set by Groovy). No dialog is opened.
    * 
-   * @param list
-   * @param separator
-   * @return concatenated string
+   * @param af
+   * @param treeType
+   * @param modelName
+   * @return null, or the string "label.you_need_at_least_n_sequences" if number
+   *         of sequences selected is inappropriate
    */
-  public static String arrayToSeparatorList(String[] list, String separator)
+  @Override
+  public Object openTreePanel(AlignFrame af, String treeType,
+          String modelName)
   {
-    // TODO use StringUtils version
-    StringBuffer v = new StringBuffer();
-    if (list != null && list.length > 0)
+    if (af == null)
     {
-      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();
+      af = Jalview.getCurrentAlignFrame();
     }
-    // if (debug)
-    // {
-    // System.err.println(
-    // "Returning empty '" + separator + "' separated List\n");
-    // }
-    return "" + separator;
-  }
-
-  public String arrayToSeparatorList(String[] array)
-  {
-    return arrayToSeparatorList(array, separator);
+    return CalculationChooser.openTreePanel(af, treeType, modelName, null);
   }
 
-  public String getSelectedSequencesFrom(AlignFrame alf, String sep)
+  @Override
+  public String orderAlignmentBy(AlignFrame alf, String order,
+          String undoName, String sep)
   {
-    StringBuffer result = new StringBuffer("");
     if (sep == null || sep.length() == 0)
     {
-      sep = separator; // "+0x00AC;
+      sep = separator;
     }
-    AlignViewport v = alf.getViewport();
-    if (v.getSelectionGroup() != null)
+    String[] ids = separatorListToArray(order, sep);
+    SequenceI[] sqs = null;
+    if (ids != null && ids.length > 0)
     {
-      SequenceI[] seqs = v.getSelectionGroup()
-              .getSequencesInOrder(v.getAlignment());
-
-      for (int i = 0; i < seqs.length; i++)
+      if (alf == null)
       {
-        result.append(seqs[i].getName());
-        result.append(sep);
+        alf = Jalview.getCurrentAlignFrame();
+      }
+      jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
+              alf.getViewport().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 "";
+    }
+    ;
+    final AlignmentOrder aorder = new AlignmentOrder(sqs);
 
-    return result.toString();
+    if (undoName != null && undoName.trim().length() == 0)
+    {
+      undoName = null;
+    }
+    final String _undoName = undoName;
+    // TODO: deal with synchronization here: cannot raise any events until after
+    // this has returned.
+    return alf.sortBy(aorder, _undoName) ? "true" : "";
   }
 
-  public void setFeatureGroupStateOn(final AlignFrame alf,
-          final String groups, boolean state)
+  @Override
+  public String orderBy(String order, String undoName)
   {
-    java.awt.EventQueue.invokeLater(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        alf.setFeatureGroupState(
-                separatorListToArray(groups, separator), state);
-      }
-    });
+    return orderBy(order, undoName, null);
   }
 
-  public String getFeatureGroupsOfStateOn(AlignFrame alf, boolean visible)
+  @Override
+  public String orderBy(String order, String undoName, String sep)
   {
-    return arrayToSeparatorList(
-            alf.getFeatureGroupsOfState(visible));
+    return orderAlignmentBy(Jalview.getCurrentAlignFrame(), order, undoName,
+            sep);
   }
 
-  public void scrollViewToIn(final AlignFrame alf, final String topRow,
-          final String leftHandColumn)
+  /**
+   * Allow an outside entity to initiate the second half of argument parsing
+   * (only).
+   * 
+   * @param args
+   * @return null is good
+   */
+  @Override
+  public Object parseArguments(String[] args)
   {
-    // TODO test
-    java.awt.EventQueue.invokeLater(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        try
-        {
-          alf.scrollTo(Integer.valueOf(topRow).intValue(),
-                  Integer.valueOf(leftHandColumn).intValue());
 
-        } catch (Exception ex)
-        {
-          System.err.println("Couldn't parse integer arguments (topRow='"
-                  + topRow + "' and leftHandColumn='" + leftHandColumn
-                  + "')");
-          ex.printStackTrace();
-        }
-      }
-    });
+    try
+    {
+      Jalview.getInstance().parseArguments(new ArgsParser(args), false);
+      return null;
+    } catch (Throwable t)
+    {
+      return t;
+    }
   }
 
-  public void scrollViewToRowIn(final AlignFrame alf, final String topRow)
+  @Override
+  public void removeSelectionListener(AlignFrame af, String listener)
   {
-    // TODO test
 
-    java.awt.EventQueue.invokeLater(new Runnable()
+    List<SelectionListener> listeners = Desktop
+            .getStructureSelectionManager().getListeners();
+    for (int i = listeners.size(); --i >= 0;)
     {
-      @Override
-      public void run()
+      SelectionListener l = listeners.get(i);
+      if (l instanceof JsSelectionListener
+              && ((JsSelectionListener) l).isFor(af, listener))
       {
-        try
-        {
-          alf.scrollToRow(Integer.valueOf(topRow).intValue());
-
-        } catch (Exception ex)
-        {
-          System.err.println("Couldn't parse integer arguments (topRow='"
-                  + topRow + "')");
-          ex.printStackTrace();
-        }
-
+        listeners.remove(i);
+        break;
       }
-    });
+    }
   }
 
+  @Override
   public void scrollViewToColumnIn(final AlignFrame alf,
           final String leftHandColumn)
   {
-    // TODO test
     java.awt.EventQueue.invokeLater(new Runnable()
     {
 
@@ -864,8 +1482,9 @@ public class JalviewAppLoader
       {
         try
         {
-          alf
-                  .scrollToColumn(Integer.valueOf(leftHandColumn).intValue());
+          (alf == null ? Jalview.getCurrentAlignFrame() : alf)
+                  .scrollToColumn(
+                          Integer.valueOf(leftHandColumn).intValue());
 
         } catch (Exception ex)
         {
@@ -875,145 +1494,115 @@ public class JalviewAppLoader
           ex.printStackTrace();
         }
       }
-    });
-
-  }
-
-  public boolean addPdbFile(AlignFrame alf, String sequenceId,
-          String pdbEntryString, String pdbFile)
-  {
-    AlignFrame alFrame = alf;
-    SequenceI toaddpdb = alFrame.getViewport().getAlignment()
-            .findName(sequenceId);
-    boolean needtoadd = false;
-    if (toaddpdb != null)
-    {
-      Vector<PDBEntry> pdbe = toaddpdb.getAllPDBEntries();
-      PDBEntry pdbentry = null;
-      if (pdbe != null && pdbe.size() > 0)
-      {
-        for (int pe = 0, peSize = pdbe.size(); pe < peSize; pe++)
-        {
-          pdbentry = pdbe.elementAt(pe);
-          if (!pdbentry.getId().equals(pdbEntryString)
-                  && !pdbentry.getFile().equals(pdbFile))
-          {
-            pdbentry = null;
-          }
-          else
-          {
-            continue;
-          }
-        }
-      }
-      if (pdbentry == null)
-      {
-        pdbentry = new PDBEntry();
-        pdbentry.setId(pdbEntryString);
-        pdbentry.setFile(pdbFile);
-        needtoadd = true; // add this new entry to sequence.
-      }
-      // resolve data source
-      // TODO: this code should be a refactored to an io package
-      DataSourceType protocol = AppletFormatAdapter.resolveProtocol(pdbFile,
-              FileFormat.PDB);
-      if (protocol == null)
-      {
-        return false;
-      }
-      if (needtoadd)
-      {
-        pdbentry.setProperty("protocol", protocol);
-        toaddpdb.addPDBId(pdbentry);
-        alFrame.alignPanel.getStructureSelectionManager()
-                .registerPDBEntry(pdbentry);
-      }
-    }
-    return true;
+    });
+
   }
 
-  public AlignFrame loadAlignment(String text, int width, int height,
-          String title)
+  @Override
+  public void scrollViewToIn(final AlignFrame alf, final String topRow,
+          final String leftHandColumn)
   {
-    AlignmentI al = null;
-
-    try
+    // TODO test
+    java.awt.EventQueue.invokeLater(new Runnable()
     {
-      FileFormatI format = new IdentifyFile().identify(text,
-              DataSourceType.PASTE);
-      al = new AppletFormatAdapter().readFile(text, DataSourceType.PASTE,
-              format);
-      if (al.getHeight() > 0)
+      @Override
+      public void run()
       {
-        return new AlignFrame(al, width, height, title);
+        try
+        {
+          (alf == null ? Jalview.getCurrentAlignFrame() : alf).scrollTo(
+                  Integer.valueOf(topRow).intValue(),
+                  Integer.valueOf(leftHandColumn).intValue());
+
+        } catch (Exception ex)
+        {
+          System.err.println("Couldn't parse integer arguments (topRow='"
+                  + topRow + "' and leftHandColumn='" + leftHandColumn
+                  + "')");
+          ex.printStackTrace();
+        }
       }
-    } catch (IOException ex)
-    {
-      ex.printStackTrace();
-    }
-    return null;
+    });
   }
 
-  public String getFeatureGroupsOn(AlignFrame alf)
+  @Override
+  public void scrollViewToRowIn(final AlignFrame alf, final String topRow)
   {
-    return arrayToSeparatorList(
-            alf.getFeatureGroups());
-  }
+    // TODO test
 
-  public void highlightIn(final AlignFrame 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.getViewport().getAlignment()
-                    .getSequencesArray());
-    final SequenceI sq = matcher.findIdMatch(sequenceId);
-    if (sq != null)
+    java.awt.EventQueue.invokeLater(new Runnable()
     {
-      int apos = -1;
-      try
-      {
-        apos = Integer.valueOf(position).intValue();
-        apos--;
-      } catch (NumberFormatException ex)
-      {
-        return;
-      }
-      final int pos = apos;
-      // use vamsas listener to broadcast to all listeners in scope
-      if (alignedPosition != null && (alignedPosition.trim().length() == 0
-              || alignedPosition.toLowerCase().indexOf("false") > -1))
+      @Override
+      public void run()
       {
-        java.awt.EventQueue.invokeLater(new Runnable()
+        try
         {
-          @Override
-          public void run()
-          {
-            StructureSelectionManager
-                    .getStructureSelectionManager(Desktop.getInstance())
-                    .mouseOverVamsasSequence(sq, sq.findIndex(pos), null);
-          }
-        });
-      }
-      else
-      {
-        java.awt.EventQueue.invokeLater(new Runnable()
+          (alf == null ? Jalview.getCurrentAlignFrame() : alf)
+                  .scrollToRow(Integer.valueOf(topRow).intValue());
+
+        } catch (Exception ex)
         {
-          @Override
-          public void run()
-          {
-            StructureSelectionManager
-                    .getStructureSelectionManager(Desktop.getInstance())
-                    .mouseOverVamsasSequence(sq, pos, null);
-          }
-        });
+          System.err.println("Couldn't parse integer arguments (topRow='"
+                  + topRow + "')");
+          ex.printStackTrace();
+        }
+
       }
-    }
+    });
+  }
+
+  @Override
+  public void select(String sequenceIds, String columns)
+  {
+    selectIn(Jalview.getCurrentAlignFrame(), sequenceIds, columns, null);
   }
 
-  public void selectIn(final AlignFrame alf, String sequenceIds,
-          String columns, String sep)
+  @Override
+  public void select(String sequenceIds, String columns, String sep)
   {
+    selectIn(null, sequenceIds, columns, sep);
+  }
+
+  // @Override
+  // public AlignFrame newView()
+  // {
+  // return newViewFrom(null, null);
+  // }
+  //
+  // @Override
+  // public AlignFrame newView(String name)
+  // {
+  // return newViewFrom(null, name);
+  // }
+  //
+  // @Override
+  // public AlignFrame newViewFrom(AlignFrame alf)
+  // {
+  // return newViewFrom(alf, null);
+  // }
+  //
+  // @Override
+  // public AlignFrame newViewFrom(AlignFrame alf, String name)
+  // {
+  // if (alf == null)
+  // {
+  // alf = Jalview.getCurrentAlignFrame();
+  // }
+  // return appLoader.newViewFrom(alf, name);
+  // }
+
+  @Override
+  public void selectIn(AlignFrame alf, String sequenceIds, String columns)
+  {
+    selectIn(alf, sequenceIds, columns, null);
+  }
+
+  @Override
+  public void selectIn(AlignFrame af, String sequenceIds, String columns,
+          String sep)
+  {
+    AlignFrame alf = (af == null ? Jalview.getCurrentAlignFrame() : af);
+
     if (sep == null || sep.length() == 0)
     {
       sep = separator;
@@ -1027,14 +1616,13 @@ public class JalviewAppLoader
       }
     }
     // deparse fields
-    String[] ids = JalviewAppLoader.separatorListToArray(sequenceIds, sep);
-    String[] cols = JalviewAppLoader.separatorListToArray(columns, sep);
+    String[] ids = separatorListToArray(sequenceIds, sep);
+    String[] cols = separatorListToArray(columns, sep);
     final SequenceGroup sel = new SequenceGroup();
     final ColumnSelection csel = new ColumnSelection();
     AlignmentI al = alf.getViewport().getAlignment();
     jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
-            alf.getViewport().getAlignment()
-                    .getSequencesArray());
+            alf.getViewport().getAlignment().getSequencesArray());
     int start = 0, end = al.getWidth(), alw = al.getWidth();
     boolean seqsfound = true;
     if (ids != null && ids.length > 0)
@@ -1218,283 +1806,411 @@ public class JalviewAppLoader
         @Override
         public void run()
         {
-          alf.select(sel, csel, alf
-                  .getCurrentView().getAlignment().getHiddenColumns());
+          alf.select(sel, csel,
+                  alf.getCurrentView().getAlignment().getHiddenColumns());
         }
       });
     }
   }
 
-  public String getAlignmentOrderFrom(AlignFrame alf, String sep)
+  // public AlignFrame newViewFrom(AlignFrame alf, String name)
+  // {
+  // return (AlignFrame) alf.newView(name, true);
+  // }
+  //
+  @Override
+  public String[] separatorListToArray(String list)
   {
-    AlignmentI alorder = alf.getViewport().getAlignment();
-    String[] order = new String[alorder.getHeight()];
-    for (int i = 0; i < order.length; i++)
-    {
-      order[i] = alorder.getSequenceAt(i).getName();
-    }
-    return arrayToSeparatorList(order, sep);
+    return separatorListToArray(list, separator);
   }
 
-  public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
-          String format, String suffix)
+  @Override
+  public void setFeatureGroupState(String groups, boolean state)
+  { // JalviewLite API
+    setFeatureGroupStateOn(null, groups, state);
+  }
+
+  @Override
+  public void setFeatureGroupStateOn(final AlignFrame alf,
+          final String groups, boolean state)
   {
-    try
+
+    java.awt.EventQueue.invokeLater(new Runnable()
     {
-      AlignViewport vp = alf.getViewport();
-      FileFormatI theFormat = FileFormats.getInstance().forName(format);
-      boolean seqlimits = (suffix == null
-              || suffix.equalsIgnoreCase("true"));
-      if (vp.getSelectionGroup() != null)
+      @Override
+      public void run()
       {
-        // 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(vp.getSelectionAsNewSequence()),
-                seqlimits);
-        return reply;
+        (alf == null ? Jalview.getCurrentAlignFrame() : alf)
+                .setFeatureGroupState(
+                        separatorListToArray(groups, separator), state);
       }
-    } catch (IllegalArgumentException ex)
+    });
+  }
+
+  @Override
+  public void setSelectionListener(AlignFrame af, String listener)
+  {
+    Desktop.getStructureSelectionManager()
+            .addSelectionListener(new JsSelectionListener(af, listener));
+  }
+
+  @Override
+  public void setSelectionListener(String listener)
+  {
+    Desktop.getStructureSelectionManager()
+            .addSelectionListener(new JsSelectionListener(null, listener));
+  }
+
+  @Override
+  public void setSeparator(String separator)
+  {
+    this.separator = separator;
+  }
+
+  @Override
+  public void showOverview()
+  {
+    Jalview.getCurrentAlignFrame().overviewMenuItem_actionPerformed(null);
+  }
+
+  /**
+   * Allowing for a JavaScript function here.
+   */
+  public void callInitCallback()
+  {
+    Object initjscallback = getAppletParameter("oninit", false);
+    if (initjscallback != null)
     {
-      ex.printStackTrace();
-      return "Error retrieving alignment, possibly invalid format specifier: "
-              + format;
+      try
+      {
+        doSendCallback(initjscallback, new Object[0]);
+      } catch (Exception e)
+      {
+        System.err.println("Exception when executing _oninit callback '"
+                + initjscallback + "'.");
+        e.printStackTrace();
+      }
+    }
+  }
+
+  /**
+   * Pass the provided array prepended with Jalview.this
+   * 
+   * Appropriated from org.jmol.appletjs.Jmol
+   * 
+   * @param callback
+   *          a window function or "alert"
+   * @param data
+   * @return String return from the callback method.
+   */
+  public String doSendCallback(Object callback, Object[] data)
+  {
+    Jalview me = Jalview.getInstance();
+
+    if (me != null && callback != null)
+    {
+      /**
+       * @j2sNative
+       * 
+       *            try{
+       * 
+       *            if (callback == "alert") { alert(data[0]); return ""; } var
+       *            o; if (typeof callback == "function") { o = callback; } else
+       *            { if (!callback)return; var tokens = callback.split("."); o
+       *            = window[tokens[0]]; for (var i = 1; i < tokens.length; i++)
+       *            o = o[tokens[i]]; } var a = [me]; for (var i = 0; i <
+       *            data.length; i++) a.push(data[i] ? data[i].booleanValue &&
+       *            (data[i] = data[i].booleanValue()) : data[i]); return
+       *            o.apply(null,a) } catch (e) { System.out.println(callback +
+       *            " failed " + e); }
+       */
     }
     return "";
   }
 
-  public String orderAlignmentBy(AlignFrame alf, String order,
-          String undoName, String sep)
+  private DataSourceType resolveFileProtocol(String[] retPath)
   {
-    if (sep == null || sep.length() == 0)
+    String path = retPath[0];
+    /*
+     * is it paste data?
+     */
+    if (path.startsWith("PASTE"))
     {
-      sep = separator;
+      retPath[0] = path.substring(5);
+      return DataSourceType.PASTE;
     }
-    String[] ids = JalviewAppLoader.separatorListToArray(order, sep);
-    SequenceI[] sqs = null;
-    if (ids != null && ids.length > 0)
+
+    /*
+     * is it a URL?
+     */
+    if (path.indexOf("://") >= 0)
     {
-      jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
-              alf.getViewport().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;
-      }
+      return DataSourceType.URL;
     }
-    if (sqs == null)
+
+    /*
+     * try relative to document root
+     */
+    URL documentBase = getDocumentBase();
+    String withDocBase = resolveUrlForLocalOrAbsolute(path, documentBase);
+    if (HttpUtils.isValidUrl(withDocBase))
+    {
+      // if (debug)
+      // {
+      // System.err.println("Prepended document base '" + documentBase
+      // + "' to make: '" + withDocBase + "'");
+      // }
+      retPath[0] = withDocBase;
+      return DataSourceType.URL;
+    }
+
+    /*
+     * try relative to codebase (if different to document base)
+     */
+    URL codeBase = getCodeBase();
+    String withCodeBase = resolveUrlForLocalOrAbsolute(path, codeBase);
+    if (!withCodeBase.equals(withDocBase)
+            && HttpUtils.isValidUrl(withCodeBase))
     {
-      return "";
+      // if (debug)
+      // {
+      // System.err.println("Prepended codebase '" + codeBase
+      // + "' to make: '" + withCodeBase + "'");
+      // }
+      retPath[0] = withCodeBase;
+      return DataSourceType.URL;
     }
-    ;
-    final AlignmentOrder aorder = new AlignmentOrder(sqs);
 
-    if (undoName != null && undoName.trim().length() == 0)
+    /*
+     * try locating by classloader; try this last so files in the directory
+     * are resolved using document base
+     */
+    if (inArchive(getClass(), path))
     {
-      undoName = null;
+      return DataSourceType.CLASSLOADER;
     }
-    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 null;
   }
 
-  public String getAlignmentFrom(AlignFrame alf, String format,
-          String suffix)
+  /**
+   * Discovers whether the given file is in the Applet Archive
+   * 
+   * @param f
+   *          String
+   * @return boolean
+   */
+  private static boolean inArchive(Class<?> c, String f)
   {
+    // This might throw a security exception in certain browsers
+    // Netscape Communicator for instance.
     try
     {
-      boolean seqlimits = (suffix == null
-              || suffix.equalsIgnoreCase("true"));
-
-      FileFormatI theFormat = FileFormats.getInstance().forName(format);
-      String reply = new AppletFormatAdapter().formatSequences(theFormat,
-              alf.getViewport().getAlignment(), seqlimits);
-      return reply;
-    } catch (IllegalArgumentException ex)
+      boolean rtn = (c.getResourceAsStream("/" + f) != null);
+      return rtn;
+    } catch (Exception ex)
     {
-      ex.printStackTrace();
-      return "Error retrieving alignment, possibly invalid format specifier: "
-              + format;
+      System.out.println("Exception checking resources: " + f + " " + ex);
+      return false;
     }
   }
 
-  public void loadAnnotationFrom(AlignFrame alf, String annotation)
+  /**
+   * form a complete URL given a path to a resource and a reference location on
+   * the same server
+   * 
+   * @param targetPath
+   *          - an absolute path on the same server as localref or a document
+   *          located relative to localref
+   * @param localref
+   *          - a URL on the same server as url
+   * @return a complete URL for the resource located by url
+   */
+  public static String resolveUrlForLocalOrAbsolute(String targetPath,
+          URL localref)
   {
-    if (new AnnotationFile().annotateAlignmentView(
-            alf.getViewport(), annotation,
-            DataSourceType.PASTE))
+    String resolvedPath = "";
+    if (targetPath.startsWith("/"))
     {
-      alf.alignPanel.fontChanged();
-      alf.alignPanel.setScrollValues(0, 0);
+      String codebase = localref.toString();
+      String localfile = localref.getFile();
+      resolvedPath = codebase.substring(0,
+              codebase.length() - localfile.length()) + targetPath;
+      return resolvedPath;
     }
-    else
+
+    /*
+     * get URL path and strip off any trailing file e.g.
+     * www.jalview.org/examples/index.html#applets?a=b is trimmed to
+     * www.jalview.org/examples/
+     */
+    String urlPath = localref.toString();
+    String directoryPath = urlPath;
+    int lastSeparator = directoryPath.lastIndexOf("/");
+    if (lastSeparator > 0)
     {
-      alf.parseFeaturesFile(annotation,
-              DataSourceType.PASTE);
+      directoryPath = directoryPath.substring(0, lastSeparator + 1);
     }
-  }
 
-  public boolean loadFeaturesFrom(AlignFrame alf, String features,
-          boolean autoenabledisplay)
-  {
-    boolean ret = alf.parseFeaturesFile(features,
-            DataSourceType.PASTE);
-    if (!ret)
+    if (targetPath.startsWith("/"))
     {
-      return false;
+      /*
+       * construct absolute URL to a file on the server - this is not allowed?
+       */
+      // String localfile = localref.getFile();
+      // resolvedPath = urlPath.substring(0,
+      // urlPath.length() - localfile.length())
+      // + targetPath;
+      resolvedPath = directoryPath + targetPath.substring(1);
     }
-    if (autoenabledisplay)
+    else
     {
-      alf.getViewport().setShowSequenceFeatures(true);
-      // this next was for a checkbox in JalviewLite
-      // ((AlignFrame) alf).getViewport().sequenceFeatures.setState(true);
+      resolvedPath = directoryPath + targetPath;
     }
-    return true;
+    // if (debug)
+    // {
+    // System.err.println(
+    // "resolveUrlForLocalOrAbsolute returning " + resolvedPath);
+    // }
+    return resolvedPath;
   }
 
   /**
-   * JavaScript interface to print the alignment frame
+   * parse the string into a list
    * 
-   * @param alf
-   * @param format
-   *          "jalview" or "gff" with or without ";includeComplement" or
-   *          ";includeNonpositional"; default with no ";" is
-   *          ";includeNonpositional"
-   * @return
+   * @param list
+   * @param separator
+   * @return elements separated by separator
    */
-  public String getFeaturesFrom(AlignFrame alf, String format)
+  public static String[] separatorListToArray(String list, String separator)
   {
-    AlignFrame f = (alf);
-
-    String features;
-    FeaturesFile formatter = new FeaturesFile();
-    format = format.toLowerCase();
-    if (format.indexOf(";") < 0)
-      format += ";includenonpositional";
-    boolean nonpos = format.indexOf(";includenonpositional") > 0;
-    boolean compl = format.indexOf(";includecomplement") >= 0;
-    if (format.startsWith("jalview"))
+    // TODO use StringUtils version (slightly different...)
+    int seplen = separator.length();
+    if (list == null || list.equals("") || list.equals(separator))
     {
-      features = formatter.printJalviewFormat(
-              f.getViewport().getAlignment().getSequencesArray(),
-              f.alignPanel.getFeatureRenderer(), nonpos, compl);
+      return null;
     }
-    else
+    Vector<String> jv = new Vector<>();
+    int cp = 0, pos;
+    while ((pos = list.indexOf(separator, cp)) > cp)
     {
-      features = formatter.printGffFormat(
-              f.getViewport().getAlignment().getSequencesArray(),
-              f.alignPanel.getFeatureRenderer(), nonpos, compl);
+      jv.addElement(list.substring(cp, pos));
+      cp = pos + seplen;
     }
-
-    if (features == null)
+    if (cp < list.length())
     {
-      features = "";
+      String c = list.substring(cp);
+      if (!c.equals(separator))
+      {
+        jv.addElement(c);
+      }
     }
-    return features;
-
+    if (jv.size() > 0)
+    {
+      String[] v = new String[jv.size()];
+      for (int i = 0; i < v.length; i++)
+      {
+        v[i] = jv.elementAt(i);
+      }
+      jv.removeAllElements();
+      return v;
+    }
+    return null;
   }
 
-  public String getAnnotationFrom(AlignFrame alf)
+  public class JsSelectionListener
+          implements jalview.structure.SelectionListener
   {
-    AlignFrame f = alf;
-    String annotation = new AnnotationFile()
-            .printAnnotationsForView(f.getViewport());
-    return annotation;
-  }
 
-  // public AlignFrame newViewFrom(AlignFrame alf, String name)
-  // {
-  // return (AlignFrame) alf.newView(name, true);
-  // }
-  //
-  public String[] separatorListToArray(String list)
-  {
-    return separatorListToArray(list, separator);
-  }
+    AlignFrame _af;
 
-  public Object[] getSelectionForListener(AlignFrame currentFrame,
-          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 AlignViewport
-              && currentFrame.getViewport() == source)
-      {
-        // should be valid if it just generated an event!
-        src = currentFrame;
+    String _listener;
 
-      }
+    public JsSelectionListener(AlignFrame af, String listener)
+    {
+      _af = af;
+      _listener = listener;
     }
-    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)
+
+    @Override
+    public void selection(SequenceGroup seqsel, ColumnSelection colsel,
+            HiddenColumns hidden, SelectionSource source)
     {
-      seqs = new String[seqsel.getSize()];
-      for (int i = 0; i < seqs.length; i++)
+      // System.err.println("Testing selection event relay to
+      // jsfunction:"+_listener);
+      String setid = "";
+      AlignFrame src = _af;
+      if (source != null)
       {
-        seqs[i] = seqsel.getSequenceAt(i).getName();
-      }
-      if (strt < seqsel.getStartRes())
-      {
-        strt = seqsel.getStartRes();
+        if (source instanceof AlignViewport
+                && Jalview.getCurrentAlignFrame().getViewport() == source)
+        {
+          src = Jalview.getCurrentAlignFrame();
+          if (src != _af)
+            return;
+        }
       }
-      if (end == -1 || end > seqsel.getEndRes())
+      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)
       {
-        end = seqsel.getEndRes();
+        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)
+      if (colsel != null && !colsel.isEmpty())
       {
-        end = colsel.getMax() + 1;
+        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());
+        }
       }
-      cols = new String[colsel.getSelected().size()];
-      for (int i = 0; i < cols.length; i++)
+      else
       {
-        cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
+        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);
+        }
+        ;
+
       }
+
+      Jalview jalview = Jalview.getInstance();
+      jalview.doSendCallback(_listener,
+              new Object[]
+              { src, setid, jalview.arrayToSeparatorList(seqs),
+                  jalview.arrayToSeparatorList(cols) });
     }
-    else
+
+    public boolean isFor(AlignFrame af, String listener)
     {
-      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 _af == af && _listener.contentEquals(listener);
     }
-    return new Object[] { src, setid, arrayToSeparatorList(seqs),
-        arrayToSeparatorList(cols) };
+
+  }
+
+  @Override
+  public AlignViewportI getViewport()
+  {
+    return Jalview.getCurrentAlignFrame().getViewport();
   }
 
-}
\ No newline at end of file
+}
similarity index 99%
rename from src/jalview/javascript/JSFunctionExec.java
rename to src/jalview/appletgui/js/JSFunctionExec.java
index 29f3fa9..247552b 100644 (file)
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.javascript;
+package jalview.appletgui.js;
 
 import jalview.bin.JalviewLite;
 
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.javascript;
+package jalview.appletgui.js;
 
 import jalview.appletgui.AlignFrame;
 
@@ -455,7 +455,7 @@ public interface JalviewLiteJsApi
    *          - separator separated list of PDB file URIs that this viewer is
    *          handling. These files must be in the same order they appear in
    *          Jmol (e.g. first one is frame 1, second is frame 2, etc).
-   * @see jalview.javascript.MouseOverStructureListener
+   * @see jalview.appletgui.js.MouseOverStructureListener
    */
   public abstract void setStructureListener(String listener,
           String modelSet);
similarity index 97%
rename from src/jalview/javascript/JsCallBack.java
rename to src/jalview/appletgui/js/JsCallBack.java
index 76d6e8d..2fe4dac 100644 (file)
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.javascript;
+package jalview.appletgui.js;
 
 public interface JsCallBack
 {
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.javascript;
+package jalview.appletgui.js;
 
 import jalview.appletgui.AlignFrame;
 import jalview.bin.JalviewLite;
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.javascript;
+package jalview.appletgui.js;
 
 import jalview.appletgui.AlignFrame;
 import jalview.bin.JalviewLite;
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.javascript;
+package jalview.appletgui.js;
 
 import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
 import jalview.appletgui.AlignFrame;
+import jalview.appletgui.js.JsCallBack;
 import jalview.bin.JalviewLite;
 import jalview.datamodel.SequenceI;
 import jalview.ext.jmol.JmolCommands;
index 6a23c39..a6c87b1 100644 (file)
@@ -1,10 +1,11 @@
-package jalview.bin;
 
-import jalview.gui.Preferences;
+package jalview.bin;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
-import java.util.Vector;
+
+import jalview.gui.Preferences;
 
 /**
  * Collection of all known applet tags from JalviewLite
@@ -13,7 +14,7 @@ import java.util.Vector;
  *
  */
 @SuppressWarnings("serial")
-public class AppletParams extends HashMap<String, String>
+public class AppletParams extends HashMap<String, Object>
 {
 
   private final static String[] params = { "alignpdbfiles",
@@ -37,18 +38,10 @@ public class AppletParams extends HashMap<String, String>
       "userDefinedColour", "widthScale", "windowHeight", "windowWidth",
       "wrap", };
 
-  public AppletParams(Map<String, String> info)
-  {
-    for (int i = params.length; --i >= 0;)
-    {
-      put(params[i], info.get(params[i]));
-    }
-  }
-
   public String getParam(String param, String def)
   {
-    String val = get(param);
-    return (val != null ? val : def);
+    Object val = get(param);
+    return (val != null ? val.toString() : def);
   }
 
   // <applet
@@ -103,14 +96,40 @@ public class AppletParams extends HashMap<String, String>
 
   public AppletParams()
   {
-    // TODO Auto-generated constructor stub
+  }
+
+  public static AppletParams getAppletParams(Map<String, Object> map,
+          List<String> vargs)
+  {
+    AppletParams appletParams = new AppletParams();
+    String resourcePath = getString(map, "resourcePath");
+    if (resourcePath == null)
+      resourcePath = "";
+    if (resourcePath.length() > 0 && !resourcePath.endsWith("/"))
+    {
+      resourcePath += "/";
+    }
+    for (int i = params.length; --i >= 0;)
+    {
+      String prefName = params[i];
+      Object value = map.get(prefName);
+      if (value != null)
+        addParam(vargs, prefName, value, appletParams, resourcePath);
+    }
+    return appletParams;
+  }
+
+  private static String getString(Map<String, Object> map, String key)
+  {
+    Object o = map.get(key);  
+    return (o == null ? null : o.toString());
   }
 
   public static AppletParams getAppletParams(String[] args,
-          Vector<String> vargs)
+          List<String> vargs)
   {
     AppletParams appletParams = new AppletParams();
-    String resourcePath = null;
+    String resourcePath = "";
     for (int i = args.length; --i > 0;) // > 0 is correct, not >=0
     {
       if (args[i].startsWith("name=\"Info.resourcePath\""))
@@ -129,265 +148,271 @@ public class AppletParams extends HashMap<String, String>
       if (arg.startsWith("name="))
       {
         String prefName = getAttr(arg, "name");
-        String appletName = prefName.toLowerCase();
-        String argName = prefName;
         String value = getAttr(arg, "value");
+        addParam(vargs, prefName, value, appletParams, resourcePath);
+      }
+    }
+    return appletParams;
+  }
 
-        // note that Application arguments ARE case-sensitive, but
-        // Applet.getParameter() is not.
+  private static void addParam(List<String> vargs, String prefName,
+          Object value, AppletParams appletParams, String resourcePath)
+  {
 
-        switch (appletName)
-        {
+    // note that Application arguments ARE case-sensitive, but
+    // Applet.getParameter() is not.
 
-        case "file":
-          argName = "open";
-          appletName = null;
-          value = resourcePath + value;
-          break;
-        case "file2":
-          argName = "open2";
-          prefName = null;
-          value = resourcePath + value;
-          break;
-        case "features":
-        case "jnetfile":
-        case "jpredfile":
-        case "pdbfile":
-        case "scorefile":
-        case "sequence":
-          // setting argName to null indicates that we want
-          // JalviewAppLoader to take care of this.
-          prefName = argName = null;
-          value = resourcePath + value;
-          break;
-        case "tree":
-        case "treefile":
-          // setting appletName to null indicates that we want
-          // Jalview.doMain to taken care of this as Jalview args
-          argName = "tree";
-          appletName = null;
-          value = resourcePath + value;
-          break;
+    String appletName = prefName.toLowerCase();
+    String argName = prefName;
+    switch (appletName)
+    {
 
-        // non-loading preferences
+    case "file":
+      argName = "open";
+      appletName = null;
+      value = resourcePath + value;
+      break;
+    case "file2":
+      argName = "open2";
+      prefName = null;
+      value = resourcePath + value;
+      break;
+    case "features":
+    case "jnetfile":
+    case "jpredfile":
+    case "pdbfile":
+    case "scorefile":
+    case "sequence":
+      // setting argName to null indicates that we want
+      // JalviewAppLoader to take care of this.
+      prefName = argName = null;
+      value = resourcePath + value;
+      break;
+    case "tree":
+    case "treefile":
+      // setting appletName to null indicates that we want
+      // Jalview.doMain to taken care of this as Jalview args
+      argName = "tree";
+      appletName = null;
+      value = resourcePath + value;
+      break;
 
-        case "defaultcolour":
-          prefName = Preferences.DEFAULT_COLOUR;
-          break;
-        case "defaultcolournuc":
-          prefName = Preferences.DEFAULT_COLOUR_NUC;
-          break;
-        case "defaultcolourprot":
-          prefName = Preferences.DEFAULT_COLOUR_PROT;
-          break;
-        case "annotationcolour_max":
-          prefName = Preferences.ANNOTATIONCOLOUR_MAX;
-          break;
-        case "annotationcolour_min":
-          prefName = Preferences.ANNOTATIONCOLOUR_MIN;
-          break;
-        case "enablesplitframe":
-          prefName = Preferences.ENABLE_SPLIT_FRAME;
-          break;
-        case "centrecolumnlabels":
-          prefName = Preferences.CENTRE_COLUMN_LABELS;
-          break;
-        case "sortby":
-          prefName = Preferences.SORT_ALIGNMENT; // id, etc.
-          break;
-        case "normalisesequencelogo":
-          prefName = Preferences.NORMALISE_CONSENSUS_LOGO;
-          break;
-        case "relaxedidmatch":
-          prefName = Preferences.RELAXEDSEQIDMATCHING;
-          break;
-        case "scaleproteinascdna":
-          prefName = Preferences.SCALE_PROTEIN_TO_CDNA;
-          break;
-        case "userdefinedcolour":
-          argName = "colour";
-          prefName = Preferences.USER_DEFINED_COLOURS;
-          break;
-        case "wrap":
-          prefName = Preferences.WRAP_ALIGNMENT;
-          break;
+    // non-loading preferences
 
-        // implemented; not tested:
+    case "defaultcolour":
+      prefName = Preferences.DEFAULT_COLOUR;
+      break;
+    case "defaultcolournuc":
+      prefName = Preferences.DEFAULT_COLOUR_NUC;
+      break;
+    case "defaultcolourprot":
+      prefName = Preferences.DEFAULT_COLOUR_PROT;
+      break;
+    case "annotationcolour_max":
+      prefName = Preferences.ANNOTATIONCOLOUR_MAX;
+      break;
+    case "annotationcolour_min":
+      prefName = Preferences.ANNOTATIONCOLOUR_MIN;
+      break;
+    case "enablesplitframe":
+      prefName = Preferences.ENABLE_SPLIT_FRAME;
+      break;
+    case "centrecolumnlabels":
+      prefName = Preferences.CENTRE_COLUMN_LABELS;
+      break;
+    case "sortby":
+      prefName = Preferences.SORT_ALIGNMENT; // id, etc.
+      break;
+    case "normalisesequencelogo":
+      prefName = Preferences.NORMALISE_CONSENSUS_LOGO;
+      break;
+    case "relaxedidmatch":
+      prefName = Preferences.RELAXEDSEQIDMATCHING;
+      break;
+    case "scaleproteinascdna":
+      prefName = Preferences.SCALE_PROTEIN_TO_CDNA;
+      break;
+    case "userdefinedcolour":
+      argName = "colour";
+      prefName = Preferences.USER_DEFINED_COLOURS;
+      break;
+    case "wrap":
+      prefName = Preferences.WRAP_ALIGNMENT;
+      break;
 
-        case "oninit":
-          prefName = null;
-          break;
-        case "annotations":
-          value = resourcePath + value;
-          argName = null;
-          break;
-        case "hidefeaturegroups":
-          // TODO
-          break;
-        case "pdbseq":
-          argName = prefName = null;
-          break;
-        case "sortbytree":
-          prefName = Preferences.SORT_BY_TREE;
-          value = checkTF(value);
-          appletName = null; // taken care of by Jalview
-          break;
-        case "format":
-          break;
-        case "alignpdbfiles":
-          argName = prefName = null;
-          break;
-        case "separator":
-          break;
+    // implemented; not tested:
 
-        // TODO: probably not relevant?
+    case "oninit":
+      prefName = null;
+      break;
+    case "annotations":
+      value = resourcePath + value;
+      argName = null;
+      break;
+    case "hidefeaturegroups":
+      // TODO
+      break;
+    case "pdbseq":
+      argName = prefName = null;
+      break;
+    case "sortbytree":
+      prefName = Preferences.SORT_BY_TREE;
+      value = checkTF(value);
+      appletName = null; // taken care of by Jalview
+      break;
+    case "format":
+      break;
+    case "alignpdbfiles":
+      argName = prefName = null;
+      break;
+    case "separator":
+      break;
 
-        case "rgb":
-          prefName = null; // TODO no background for application?
-          break;
-        case "externalstructureviewer":
-          break;
-        case "application_url":
-          break;
-        case "automaticscrolling":
-          break;
-        case "heightscale":
-          break;
-        case "jalviewhelpurl":
-          break;
-        case "label":
-          break;
-        case "linklabel_":
-          prefName = "linkLabel_";
-          break;
-        case "linklabel_1":
-          prefName = "linkLabel_1";
-          break;
-        case "linkurl_":
-          prefName = "linkURL_";
-          break;
+    // TODO: probably not relevant?
 
-        // unknown:
+    case "rgb":
+      prefName = null; // TODO no background for application?
+      break;
+    case "externalstructureviewer":
+      break;
+    case "application_url":
+      break;
+    case "automaticscrolling":
+      break;
+    case "heightscale":
+      break;
+    case "jalviewhelpurl":
+      break;
+    case "label":
+      break;
+    case "linklabel_":
+      prefName = "linkLabel_";
+      break;
+    case "linklabel_1":
+      prefName = "linkLabel_1";
+      break;
+    case "linkurl_":
+      prefName = "linkURL_";
+      break;
 
-        case "nojmol":
-        case "normaliselogo":
-        case "resolvetocodebase":
-        case "uppercase":
-        case "widthscale":
-        case "windowheight":
-        case "windowwidth":
-          argName = prefName = null;
-          break;
+    // unknown:
 
-        // TRUE/FALSE
+    case "nojmol":
+    case "normaliselogo":
+    case "resolvetocodebase":
+    case "uppercase":
+    case "widthscale":
+    case "windowheight":
+    case "windowwidth":
+      argName = prefName = null;
+      break;
 
-        case "debug":
-          value = checkTF(value);
-          break;
-        case "embedded":
-          value = checkTF(value);
-          break;
-        case "showbutton":
-          value = checkTF(value);
-          break;
-        case "showannotation":
-          prefName = Preferences.SHOW_ANNOTATIONS;
-          value = checkTF(value);
-          break;
-        case "showconsensus":
-          prefName = Preferences.SHOW_CONSENSUS_LOGO;
-          value = checkTF(value);
-          break;
-        case "showconsensushistogram":
-          prefName = Preferences.SHOW_CONSENSUS_HISTOGRAM;
-          value = checkTF(value);
-          break;
-        case "showconservation":
-          prefName = Preferences.SHOW_CONSERVATION;
-          value = checkTF(value);
-          break;
-        case "showgroupconsensus":
-          prefName = Preferences.SHOW_GROUP_CONSENSUS;
-          value = checkTF(value);
-          break;
-        case "showgroupconservation":
-          prefName = Preferences.SHOW_GROUP_CONSERVATION;
-          value = checkTF(value);
-          break;
-        case "showoccupancy":
-          prefName = Preferences.SHOW_OCCUPANCY;
-          value = checkTF(value);
-          break;
-        case "showquality":
-          prefName = Preferences.SHOW_QUALITY;
-          value = checkTF(value);
-          break;
-        case "showsequencelogo":
-          prefName = Preferences.SHOW_CONSENSUS_LOGO;
-          value = checkTF(value);
-          break;
-        case "showfeaturegroups":
-          value = checkTF(value);
-          break;
-        case "showfeaturesettings":
-          value = checkTF(value);
-          break;
-        case "showfullid":
-          value = checkTF(value);
-          break;
-        case "showtreebootstraps":
-          value = checkTF(value);
-          break;
-        case "showtreedistances":
-          value = checkTF(value);
-          break;
-        case "showunconserved":
-          prefName = Preferences.SHOW_UNCONSERVED;
-          value = checkTF(value);
-          break;
-        case "showunlinkedtreenodes":
-          value = checkTF(value);
-          break;
-        default:
-          if (appletName.startsWith("pdbfile")
-                  || appletName.startsWith("sequence") && Character.isDigit(
-                          appletName.charAt(appletName.length() - 1)))
-          {
-            // could be pdbFile2, for example
-            prefName = argName = null;
-            value = resourcePath + value;
-            break;
-          }
-          // or one of the app preference names
-          break;
-        }
-        // put name and value into application args
-        if (value != null && argName != null)
-        {
-          vargs.add(argName);
-          if (value != "true")
-          {
-            vargs.add(value);
-          }
-        }
-        if (value == null)
-        {
-          value = "false";
-        }
-        System.out.println("AppletParams propName=" + prefName + " argName="
-                + argName + " appletName="
-                + appletName + " value=" + value);
-        if (appletName != null)
-        {
-          appletParams.put(appletName, value);
-        }
-        if (prefName != null)
-        {
-          Cache.setPropertyNoSave(prefName, value);
-        }
+    // TRUE/FALSE
+
+    case "debug":
+      value = checkTF(value);
+      break;
+    case "embedded":
+      value = checkTF(value);
+      break;
+    case "showbutton":
+      value = checkTF(value);
+      break;
+    case "showannotation":
+      prefName = Preferences.SHOW_ANNOTATIONS;
+      value = checkTF(value);
+      break;
+    case "showconsensus":
+      prefName = Preferences.SHOW_CONSENSUS_LOGO;
+      value = checkTF(value);
+      break;
+    case "showconsensushistogram":
+      prefName = Preferences.SHOW_CONSENSUS_HISTOGRAM;
+      value = checkTF(value);
+      break;
+    case "showconservation":
+      prefName = Preferences.SHOW_CONSERVATION;
+      value = checkTF(value);
+      break;
+    case "showgroupconsensus":
+      prefName = Preferences.SHOW_GROUP_CONSENSUS;
+      value = checkTF(value);
+      break;
+    case "showgroupconservation":
+      prefName = Preferences.SHOW_GROUP_CONSERVATION;
+      value = checkTF(value);
+      break;
+    case "showoccupancy":
+      prefName = Preferences.SHOW_OCCUPANCY;
+      value = checkTF(value);
+      break;
+    case "showquality":
+      prefName = Preferences.SHOW_QUALITY;
+      value = checkTF(value);
+      break;
+    case "showsequencelogo":
+      prefName = Preferences.SHOW_CONSENSUS_LOGO;
+      value = checkTF(value);
+      break;
+    case "showfeaturegroups":
+      value = checkTF(value);
+      break;
+    case "showfeaturesettings":
+      value = checkTF(value);
+      break;
+    case "showfullid":
+      value = checkTF(value);
+      break;
+    case "showtreebootstraps":
+      value = checkTF(value);
+      break;
+    case "showtreedistances":
+      value = checkTF(value);
+      break;
+    case "showunconserved":
+      prefName = Preferences.SHOW_UNCONSERVED;
+      value = checkTF(value);
+      break;
+    case "showunlinkedtreenodes":
+      value = checkTF(value);
+      break;
+    default:
+      if (appletName.startsWith("pdbfile")
+              || appletName.startsWith("sequence") && Character
+                      .isDigit(appletName.charAt(appletName.length() - 1)))
+      {
+        // could be pdbFile2, for example
+        prefName = argName = null;
+        value = resourcePath + value;
+        break;
       }
+      // or one of the app preference names
+      break;
+    }
+
+    // put name and value into application args
+    if (value != null && argName != null)
+    {
+      vargs.add(argName);
+      if (value != "true")
+      {
+        vargs.add(value.toString());
+      }
+    }
+    if (value == null)
+    {
+      value = "false";
+    }
+    System.out.println("AppletParams propName=" + prefName + " argName="
+            + argName + " appletName=" + appletName + " value=" + value);
+    if (appletName != null)
+    {
+      appletParams.put(appletName, value);
+    }
+    if (prefName != null)
+    {
+      Cache.setPropertyNoSave(prefName, value.toString());
     }
-    return appletParams;
   }
 
   /**
@@ -396,9 +421,9 @@ public class AppletParams extends HashMap<String, String>
    * @param value
    * @return "true" or null
    */
-  private static String checkTF(String value)
+  private static String checkTF(Object value)
   {
-    return (value.toLowerCase() == "true" ? "true" : null);
+    return (("" + value).toLowerCase() == "true" ? "true" : null);
   }
 
   /**
index 91c8838..55e760f 100644 (file)
  */
 package jalview.bin;
 
+import jalview.util.Platform;
+
 import java.net.URLDecoder;
-import java.util.Vector;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Notes: this argParser does not distinguish between parameter switches,
@@ -96,7 +99,7 @@ public class ArgsParser
 
   public static final String VSESS = "vsess";
 
-  private Vector<String> vargs = null;
+  private List<String> vargs = null;
 
   private boolean isApplet;
 
@@ -109,12 +112,18 @@ public class ArgsParser
 
   public ArgsParser(String[] args)
   {
-    vargs = new Vector<>();
+    vargs = new ArrayList<>();
     isApplet = (args.length > 0 && args[0].startsWith("<applet"));
     if (isApplet)
     {
       appletParams = AppletParams.getAppletParams(args, vargs);
     }
+    else if (Platform.isJS() && args.length == 0)
+    {
+      isApplet = true;
+      appletParams = AppletParams
+              .getAppletParams(Platform.getAppletInfoAsMap(), vargs);
+    }
     else
     {
       for (int i = 0; i < args.length; i++)
@@ -124,7 +133,7 @@ public class ArgsParser
         {
           arg = arg.substring(1);
         }
-        vargs.addElement(arg);
+        vargs.add(arg);
       }
     }
   }
@@ -146,9 +155,9 @@ public class ArgsParser
     String dc = null, ret = null;
     if (index != -1)
     {
-      ret = vargs.elementAt(index + 1).toString();
-      vargs.removeElementAt(index);
-      vargs.removeElementAt(index);
+      ret = vargs.get(index + 1).toString();
+      vargs.remove(index);
+      vargs.remove(index);
       if (utf8decode && ret != null)
       {
         try
@@ -174,7 +183,7 @@ public class ArgsParser
   {
     if (vargs.contains(arg))
     {
-      vargs.removeElement(arg);
+      vargs.remove(arg);
       return true;
     }
     else
@@ -193,12 +202,13 @@ public class ArgsParser
     return vargs.size();
   }
 
-  public String getAppletValue(String key, String def)
+  public Object getAppletValue(String key, String def, boolean asString)
   {
-    String value;
+    Object value;
     return (appletParams == null ? null
-            : (value = appletParams.get(key.toLowerCase())) != null ? value
-                    : def);
+            : (value = appletParams.get(key.toLowerCase())) == null
+                    ? def : asString ? value.toString()
+                    : value);
   }
 
 }
index ad7bad6..af9d06e 100755 (executable)
@@ -37,7 +37,6 @@ import java.security.PermissionCollection;
 import java.security.Permissions;
 import java.security.Policy;
 import java.util.HashMap;
-import java.util.Hashtable;
 import java.util.Map;
 import java.util.Vector;
 
@@ -49,24 +48,14 @@ import com.threerings.getdown.util.LaunchUtil;
 import groovy.lang.Binding;
 import groovy.util.GroovyScriptEngine;
 import jalview.api.AlignCalcWorkerI;
-import jalview.api.AlignViewportI;
-import jalview.api.JalviewApp;
-import jalview.api.StructureSelectionManagerProvider;
+import jalview.api.JalviewJSApp;
 import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
-import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
 import jalview.ext.so.SequenceOntology;
 import jalview.gui.AlignFrame;
 import jalview.gui.AlignViewport;
-import jalview.gui.AlignmentPanel;
-import jalview.gui.CalculationChooser;
 import jalview.gui.Desktop;
 import jalview.gui.Preferences;
 import jalview.gui.PromptUserConfig;
-import jalview.gui.StructureViewer;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.BioJsHTMLOutput;
 import jalview.io.DataSourceType;
@@ -79,17 +68,12 @@ import jalview.io.HtmlSvgOutput;
 import jalview.io.IdentifyFile;
 import jalview.io.NewickFile;
 import jalview.io.gff.SequenceOntologyFactory;
-import jalview.javascript.JSFunctionExec;
-import jalview.javascript.MouseOverStructureListener;
-import jalview.renderer.seqfeatures.FeatureRenderer;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
-import jalview.structure.SelectionSource;
-import jalview.structure.VamsasSource;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.ws.jws2.Jws2Discoverer;
-import netscape.javascript.JSObject;
+//import netscape.javascript.JSObject;
 
 /**
  * Main class for Jalview Application <br>
@@ -106,7 +90,7 @@ import netscape.javascript.JSObject;
  * @author $author$
  * @version $Revision$
  */
-public class Jalview implements ApplicationSingletonI, JalviewJSApi
+public class Jalview implements ApplicationSingletonI
 {
 
   // for testing those nasty messages you cannot ever find.
@@ -144,16 +128,12 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
 
   private Desktop desktop;
 
-  public static AlignFrame currentAlignFrame;
-
-  public boolean isJavaAppletTag;
+  public AlignFrame currentAlignFrame;
 
   public String appletResourcePath;
 
-  JalviewAppLoader appLoader;
-
-  protected JSFunctionExec jsFunctionExec;
-
+  JalviewJSApp app; // JalviewJS-specific JavaScript interface
+  
   private boolean noCalculation, noMenuBar, noStatus;
 
   private boolean noAnnotation;
@@ -289,11 +269,7 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
   {
 
     boolean isJS = Platform.isJS();
-    if (isJS)
-    {
-      Platform.setAppClass(this);
-    }
-    else
+    if (!isJS)
     {
       System.setSecurityManager(null);
     }
@@ -332,16 +308,11 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
 
     if (isJS)
     {
-      isJavaAppletTag = aparser.isApplet();
-      if (isJavaAppletTag)
-      {
+        app = new JalviewJSApp(aparser);
         Preferences.setAppletDefaults();
         Cache.loadProperties(usrPropsFile); // again, because we
         // might be changing defaults here?
-      }
-      System.out.println(
-              "<Applet> found: " + aparser.getValue("Info.j2sAppletID"));
-      appletResourcePath = aparser.getValue("Info.resourcePath");
+      appletResourcePath = (String) aparser.getAppletValue("resourcepath", null, true);
     }
     else
     /**
@@ -560,27 +531,7 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
     }
 
     parseArguments(aparser, true);
-  }
-
-  /**
-   * Allow an outside entity to initiate the second half of argument parsing
-   * (only).
-   * 
-   * @param args
-   * @return null is good
-   */
-  @Override
-  public Object parseArguments(String[] args)
-  {
-
-    try
-    {
-      parseArguments(new ArgsParser(args), false);
-      return null;
-    } catch (Throwable t)
-    {
-      return t;
-    }
+    
   }
 
   /**
@@ -588,7 +539,7 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
    * @param aparser
    * @param isStartup
    */
-  private void parseArguments(ArgsParser aparser, boolean isStartup)
+  public void parseArguments(ArgsParser aparser, boolean isStartup)
   {
 
     String groovyscript = null; // script to execute after all loading is
@@ -665,20 +616,18 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
           }
         }
       }
-      String fileFormat = (isJavaAppletTag
-              ? aparser.getAppletValue("format", null)
+      String fileFormat = (isJS ? (String) aparser.getAppletValue("format", null, true)
               : null);
       protocol = AppletFormatAdapter.checkProtocol(file);
       try
       {
-        format = (isJavaAppletTag && fileFormat != null
+        format = (fileFormat != null
                 ? FileFormats.getInstance().forName(fileFormat)
                 : null);
         if (format == null)
         {
           format = new IdentifyFile().identify(file, protocol);
         }
-        format = new IdentifyFile().identify(file, protocol);
       } catch (FileFormatException e1)
       {
         // TODO ?
@@ -855,12 +804,12 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
         {
           try
           {
-            System.out.println(
-                    "CMD [-tree " + data + "] executed successfully!");
             NewickFile nf = new NewickFile(data,
                     AppletFormatAdapter.checkProtocol(data));
             af.getViewport()
                     .setCurrentTree(af.showNewickTree(nf, data).getTree());
+            System.out.println(
+                    "CMD [-tree " + data + "] executed successfully!");
           } catch (IOException ex)
           {
             System.err.println("Couldn't add tree " + data);
@@ -870,11 +819,12 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
         // TODO - load PDB structure(s) to alignment JAL-629
         // (associate with identical sequence in alignment, or a specified
         // sequence)
-        if (isJavaAppletTag)
+        
+        if (isJS)
         {
-          loadAppletParams(aparser, af);
+          app.load(af);
         }
-        else if (!isJS)
+        else
         /**
          * Java only
          * 
@@ -892,11 +842,7 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
                     + "] executed successfully!");
             groovyscript = null;
           }
-        }
-        createOutputFiles(aparser, af, format);
-        while (aparser.getSize() > 0)
-        {
-          System.out.println("Unknown arg: " + aparser.nextValue());
+          createOutputFiles(aparser, af, format);
         }
       }
     }
@@ -979,7 +925,13 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
       }
       desktop.setInBatchMode(false);
     }
+
+    if (isJS && isStartup)
+    {
+      app.callInitCallback();
+    }
   }
+  
 
   /**
    * Writes an output file for each format (if any) specified in the
@@ -1003,43 +955,33 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
   private void createOutputFiles(ArgsParser aparser, AlignFrame af,
           FileFormatI format)
   {
-    String imageName = "unnamed.png";
-    while (aparser.getSize() > 1)
+    while (aparser.getSize() >= 2)
     {
       String outputFormat = aparser.nextValue();
-      String file = aparser.nextValue();
-
-      if (outputFormat.equalsIgnoreCase("png"))
+      File imageFile;
+      String fname;
+      switch (outputFormat.toLowerCase())
       {
-        af.createPNG(new File(file));
-        imageName = (new File(file)).getName();
-        System.out.println("Creating PNG image: " + file);
+      case "png":
+        imageFile = new File(aparser.nextValue());
+        af.createPNG(imageFile);
+        System.out.println(
+                "Creating PNG image: " + imageFile.getAbsolutePath());
         continue;
-      }
-      else if (outputFormat.equalsIgnoreCase("svg"))
-      {
-        File imageFile = new File(file);
-        imageName = imageFile.getName();
+      case "svg":
+        imageFile = new File(aparser.nextValue());
         af.createSVG(imageFile);
-        System.out.println("Creating SVG image: " + file);
+        System.out.println(
+                "Creating SVG image: " + imageFile.getAbsolutePath());
         continue;
-      }
-      else if (outputFormat.equalsIgnoreCase("html"))
-      {
-        File imageFile = new File(file);
-        imageName = imageFile.getName();
-        HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
-        htmlSVG.exportHTML(file);
-        System.out.println("Creating HTML image: " + file);
+      case "eps":
+        imageFile = new File(aparser.nextValue());
+        System.out.println(
+                "Creating EPS file: " + imageFile.getAbsolutePath());
+        af.createEPS(imageFile);
         continue;
-      }
-      else if (outputFormat.equalsIgnoreCase("biojsmsa"))
-      {
-        if (file == null)
-        {
-          System.err.println("The output html file must not be null");
-          return;
-        }
+      case "biojsmsa":
+        fname = new File(aparser.nextValue()).getAbsolutePath();
         try
         {
           BioJsHTMLOutput.refreshVersionInfo(
@@ -1049,37 +991,44 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
           e.printStackTrace();
         }
         BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
-        bjs.exportHTML(file);
-        System.out.println("Creating BioJS MSA Viwer HTML file: " + file);
+        bjs.exportHTML(fname);
+        System.out.println("Creating BioJS MSA Viwer HTML file: " + fname);
         continue;
-      }
-      else if (outputFormat.equalsIgnoreCase("imgMap"))
-      {
-        af.createImageMap(new File(file), imageName);
-        System.out.println("Creating image map: " + file);
+      case "html":
+        fname = new File(aparser.nextValue()).getAbsolutePath();
+        HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
+        htmlSVG.exportHTML(fname);
+        System.out.println("Creating HTML image: " + fname);
         continue;
-      }
-      else if (outputFormat.equalsIgnoreCase("eps"))
-      {
-        File outputFile = new File(file);
+      case "imgmap":
+        imageFile = new File(aparser.nextValue());
+        af.alignPanel.makePNGImageMap(imageFile, "unnamed.png");
         System.out.println(
-                "Creating EPS file: " + outputFile.getAbsolutePath());
-        af.createEPS(outputFile);
+                "Creating image map: " + imageFile.getAbsolutePath());
         continue;
       }
-
-      af.saveAlignment(file, format);
-      if (af.isSaveAlignmentSuccessful())
+      if (!Platform.isJS())
       {
-        System.out.println(
-                "Written alignment in " + format + " format to " + file);
+        // skipping outputFormat?
+        System.out.println("Unknown arg: " + outputFormat);      
+        fname = new File(aparser.nextValue()).getAbsolutePath();
+        af.saveAlignment(fname, format);
+        if (af.isSaveAlignmentSuccessful())
+        {
+          System.out.println(
+                  "Written alignment in " + format + " format to " + fname);
+        }
+        else
+        {
+          System.out.println("Error writing file " + fname + " in " + format
+                  + " format!!");
+        }
       }
-      else
+      while (aparser.getSize() > 0)
       {
-        System.out.println("Error writing file " + file + " in " + format
-                + " format!!");
+        System.out.println("Unknown arg: " + aparser.nextValue());
       }
-
+      break;
     }
 
   }
@@ -1309,14 +1258,15 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
 
   public static AlignFrame getCurrentAlignFrame()
   {
-    return Jalview.currentAlignFrame;
+    return Jalview.getInstance().currentAlignFrame;
   }
 
   public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
   {
-    Jalview.currentAlignFrame = currentAlignFrame;
+    Jalview.getInstance().currentAlignFrame = currentAlignFrame;
   }
 
+  
   /**
    * Get the SwingJS applet ID and combine that with the frameType
    * 
@@ -1326,790 +1276,11 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
    */
   public static String getAppID(String frameType)
   {
-    String id = Cache.getProperty("Info.j2sAppletID");
-    if (id == null)
-    {
-      id = "jalview";
-    }
-    return id + (frameType == null ? "" : "-" + frameType);
-  }
-
-  /**
-   * Handle all JalviewLite applet parameters
-   * 
-   * @param aparser
-   * @param af
-   */
-  private void loadAppletParams(ArgsParser aparser, AlignFrame af)
-  {
-    JalviewApp app = new JalviewApp()
-    {
-
-      // TODO BH 2019
-      //
-      // These are methods that are in JalviewLite that various classes call
-      // but are not in JalviewLiteJsApi. Or, even if they are, other classes
-      // call
-      // them to JalviewLite directly. Some may not be necessary, but they have
-      // to
-      // be at least mentioned here, or the classes calling them should
-      // reference
-      // JalviewLite itself.
-
-      private boolean alignPDBStructures; // From JalviewLite; not implemented
-
-      private Hashtable<String, Hashtable<String, String[]>> jsmessages;
-
-      private Hashtable<String, int[]> jshashes;
-
-      @Override
-      public String getParameter(String name)
-      {
-        return aparser.getAppletValue(name, null);
-      }
-
-      @Override
-      public boolean getDefaultParameter(String name, boolean def)
-      {
-        String stn;
-        return ((stn = getParameter(name)) == null ? def
-                : "true".equalsIgnoreCase(stn));
-      }
-
-      /**
-       * Get the applet-like document base even though this is an application.
-       */
-      @Override
-      public URL getDocumentBase()
-      {
-        return Platform.getDocumentBase();
-      }
-
-      /**
-       * Get the applet-like code base even though this is an application.
-       */
-      @Override
-      public URL getCodeBase()
-      {
-        return Platform.getCodeBase();
-      }
-
-      @Override
-      public AlignViewportI getViewport()
-      {
-        return af.getViewport();
-      }
-
-      /**
-       * features
-       * 
-       */
-      @Override
-      public boolean parseFeaturesFile(String filename,
-              DataSourceType protocol)
-      {
-        return af.parseFeaturesFile(filename, protocol);
-      }
-
-      /**
-       * scorefile
-       * 
-       */
-      @Override
-      public boolean loadScoreFile(String sScoreFile) throws IOException
-      {
-        af.loadJalviewDataFile(sScoreFile, null, null, null);
-        return true;
-      }
-
-      /**
-       * annotations, jpredfile, jnetfile
-       * 
-       */
-      @Override
-      public void updateForAnnotations()
-      {
-        af.updateForAnnotations();
-      }
-
-      @Override
-      public void loadTree(NewickFile fin, String treeFile)
-              throws IOException
-      {
-        // n/a -- already done by standard Jalview command line processing
-      }
-
-      @Override
-      public void setAlignPdbStructures(boolean defaultParameter)
-      {
-        alignPDBStructures = true;
-      }
-
-      @Override
-      public void newStructureView(PDBEntry pdb, SequenceI[] seqs,
-              String[] chains, DataSourceType protocol)
-      {
-        StructureViewer.launchStructureViewer(af.alignPanel, pdb, seqs);
-      }
-
-      @Override
-      public void setFeatureGroupState(String[] groups, boolean state)
-      {
-        af.setFeatureGroupState(groups, state);
-      }
-
-      @Override
-      public void alignedStructureView(PDBEntry[] pdb, SequenceI[][] seqs,
-              String[][] chains, String[] protocols)
-      {
-        System.err.println(
-                "Jalview applet interface alignedStructureView not implemented");
-      }
-
-      @Override
-      public void newFeatureSettings()
-      {
-        System.err.println(
-                "Jalview applet interface newFeatureSettings not implemented");
-      }
-
-      private Vector<Runnable> jsExecQueue;
-
-      @Override
-      public Vector<Runnable> getJsExecQueue(JSFunctionExec exec)
-      {
-        jsFunctionExec = exec;
-        return (jsExecQueue == null ? (jsExecQueue = new Vector<>())
-                : jsExecQueue);
-      }
-
-      // AppletContext deprecated
-      //
-      // @Override
-      // public AppletContext getAppletContext()
-      // {
-      // // TODO Auto-generated method stub
-      // return null;
-      // }
-      //
-      @Override
-      public boolean isJsfallbackEnabled()
-      {
-        // TODO Auto-generated method stub
-        return false;
-      }
-
-      @Override
-      public JSObject getJSObject()
-      {
-        // TODO Auto-generated method stub
-        return null;
-      }
-
-      @Override
-      public StructureSelectionManagerProvider getStructureSelectionManagerProvider()
-      {
-        // TODO Q: what exactly is this? BH
-        return null;
-      }
-
-      @Override
-      public void updateColoursFromMouseOver(Object source,
-              MouseOverStructureListener mouseOverStructureListener)
-      {
-        // TODO Auto-generated method stub
-
-      }
-
-      @Override
-      public Object[] getSelectionForListener(SequenceGroup seqsel,
-              ColumnSelection colsel, HiddenColumns hidden,
-              SelectionSource source, Object alignFrame)
-      {
-        return appLoader.getSelectionForListener(getCurrentAlignFrame(),
-                seqsel, colsel, hidden, source, alignFrame);
-      }
-
-      @Override
-      public String arrayToSeparatorList(String[] array)
-      {
-        return appLoader.arrayToSeparatorList(array);
-      }
-
-      @Override
-      public Hashtable<String, int[]> getJSHashes()
-      {
-        return (jshashes == null ? (jshashes = new Hashtable<>())
-                : jshashes);
-      }
-
-      @Override
-      public Hashtable<String, Hashtable<String, String[]>> getJSMessages()
-      {
-        return (jsmessages == null ? (jsmessages = new Hashtable<>())
-                : jsmessages);
-      }
-
-      @Override
-      public Object getFrameForSource(VamsasSource source)
-      {
-        if (source != null)
-        {
-          AlignFrame af;
-          if (source instanceof jalview.gui.AlignViewport
-                  && source == (af = getCurrentAlignFrame()).getViewport())
-          {
-            // should be valid if it just generated an event!
-            return af;
-          }
-          // 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.gui.FeatureRenderer((AlignmentPanel) vp);
-      }
-
-    };
-
-    appLoader = new JalviewAppLoader(true);
-    appLoader.load(app);
-  }
-
-  /**
-   * 
-   * @see jalview.bin.JalviewLiteJsApi#getSelectedSequences()
-   */
-  @Override
-  public String getSelectedSequences()
-  {
-    return getSelectedSequencesFrom(getCurrentAlignFrame());
+    return (Platform.isJS() ? getInstance().app.getAppID(frameType) : null);
   }
 
-  /**
-   * 
-   * @see jalview.bin.JalviewLiteJsApi#getSelectedSequences(java.lang.String)
-   */
-  @Override
-  public String getSelectedSequences(String sep)
-  {
-    return getSelectedSequencesFrom(getCurrentAlignFrame(), sep);
-  }
-
-  /**
-   * 
-   * @see jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
-   *      .AlignFrame)
-   */
-  @Override
-  public String getSelectedSequencesFrom(AlignFrame alf)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return getSelectedSequencesFrom(alf, null);
-  }
-
-  /**
-   * 
-   * @see jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
-   *      .AlignFrame, java.lang.String)
-   */
-  @Override
-  public String getSelectedSequencesFrom(AlignFrame alf, String sep)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.getSelectedSequencesFrom(alf, sep);
-  }
-
-  /**
-   * 
-   * @see jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
-   *      .AlignFrame, java.lang.String)
-   */
-  @Override
-  public void highlight(String sequenceId, String position,
-          String alignedPosition)
-  {
-    highlightIn(null, sequenceId, position, alignedPosition);
-  }
-
-  @Override
-  public void highlightIn(AlignFrame alf, String sequenceId,
-          String position, String alignedPosition)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    appLoader.highlightIn(alf, sequenceId, position, alignedPosition);
-  }
-
-  @Override
-  public void select(String sequenceIds, String columns)
-  {
-    selectIn(getCurrentAlignFrame(), sequenceIds, columns, null);
-  }
-
-  @Override
-  public void select(String sequenceIds, String columns, String sep)
-  {
-    selectIn(null, sequenceIds, columns, sep);
-  }
-
-  @Override
-  public void selectIn(AlignFrame alf, String sequenceIds, String columns)
-  {
-    selectIn(alf, sequenceIds, columns, null);
-  }
-
-  @Override
-  public void selectIn(AlignFrame alf, String sequenceIds, String columns,
-          String sep)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    appLoader.selectIn(alf, sequenceIds, columns, sep);
-  }
-
-  @Override
-  public String getSelectedSequencesAsAlignment(String format,
-          String suffix)
-  {
-    return getSelectedSequencesAsAlignmentFrom(null, format, suffix);
-  }
-
-  @Override
-  public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
-          String format, String sep)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.getSelectedSequencesAsAlignmentFrom(alf, format, sep);
-  }
-
-  @Override
-  public String getAlignmentOrder()
-  {
-    return getAlignmentFrom(getCurrentAlignFrame(), null);
-  }
-
-  @Override
-  public String getAlignmentOrderFrom(AlignFrame alf)
-  {
-    return getAlignmentFrom(alf, null);
-  }
-
-  @Override
-  public String getAlignmentOrderFrom(AlignFrame alf, String sep)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.getAlignmentOrderFrom(alf, sep);
-  }
-
-  @Override
-  public String orderBy(String order, String undoName)
-  {
-    return orderBy(order, undoName, null);
-  }
-
-  @Override
-  public String orderBy(String order, String undoName, String sep)
-  {
-    return orderAlignmentBy(getCurrentAlignFrame(), order, undoName, sep);
-  }
-
-  @Override
-  public String orderAlignmentBy(AlignFrame alf, String order,
-          String undoName, String sep)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.orderAlignmentBy(alf, order, undoName, sep);
-  }
-
-  @Override
-  public String getAlignment(String format)
-  {
-    return getAlignmentFrom(null, format, null);
-  }
-
-  @Override
-  public String getAlignmentFrom(AlignFrame alf, String format)
-  {
-    return getAlignmentFrom(alf, format, null);
-  }
-
-  @Override
-  public String getAlignment(String format, String suffix)
-  {
-    return getAlignmentFrom(getCurrentAlignFrame(), format, suffix);
-  }
-
-  @Override
-  public String getAlignmentFrom(AlignFrame alf, String format,
-          String suffix)
-  {
-    return appLoader.getAlignmentFrom(alf, format, suffix);
-  }
-
-  @Override
-  public void loadAnnotation(String annotation)
-  {
-    loadAnnotationFrom(getCurrentAlignFrame(), annotation);
-  }
-
-  @Override
-  public void loadAnnotationFrom(AlignFrame alf, String annotation)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    appLoader.loadAnnotationFrom(alf, annotation);
-  }
-
-  @Override
-  public void loadFeatures(String features, boolean autoenabledisplay)
-  {
-    loadFeaturesFrom(currentAlignFrame, features, autoenabledisplay);
-  }
-
-  @Override
-  public boolean loadFeaturesFrom(AlignFrame alf, String features,
-          boolean autoenabledisplay)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.loadFeaturesFrom(alf, features, autoenabledisplay);
-  }
-
-  @Override
-  public String getFeatures(String format)
-  {
-    return getFeaturesFrom(null, format);
-  }
-
-  @Override
-  public String getFeaturesFrom(AlignFrame alf, String format)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.getFeaturesFrom(alf, format);
-  }
-
-  @Override
-  public String getAnnotation()
-  {
-    return getAnnotationFrom(null);
-  }
-
-  @Override
-  public String getAnnotationFrom(AlignFrame alf)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.getAnnotationFrom(alf);
-  }
-
-  // @Override
-  // public AlignFrame newView()
-  // {
-  // return newViewFrom(null, null);
-  // }
-  //
-  // @Override
-  // public AlignFrame newView(String name)
-  // {
-  // return newViewFrom(null, name);
-  // }
-  //
-  // @Override
-  // public AlignFrame newViewFrom(AlignFrame alf)
-  // {
-  // return newViewFrom(alf, null);
-  // }
-  //
-  // @Override
-  // public AlignFrame newViewFrom(AlignFrame alf, String name)
-  // {
-  // if (alf == null)
-  // {
-  // alf = getCurrentAlignFrame();
-  // }
-  // return appLoader.newViewFrom(alf, name);
-  // }
-
-  @Override
-  public AlignFrame loadAlignment(String text, String title)
-  {
-    return appLoader.loadAlignment(text, AlignFrame.DEFAULT_WIDTH,
-            AlignFrame.DEFAULT_HEIGHT, title);
-  }
-
-  @Override
-  public boolean addPdbFile(AlignFrame alFrame, String sequenceId,
-          String pdbEntryString, String pdbFile)
-  {
-    if (alFrame == null)
-    {
-      alFrame = getCurrentAlignFrame();
-    }
-    return appLoader.addPdbFile(alFrame, sequenceId, pdbEntryString,
-            pdbFile);
-  }
-
-  @Override
-  public void scrollViewToIn(AlignFrame alf, String topRow,
-          String leftHandColumn)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    appLoader.scrollViewToIn(alf, topRow, leftHandColumn);
-  }
-
-  @Override
-  public void scrollViewToRowIn(AlignFrame alf, String topRow)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    appLoader.scrollViewToRowIn(alf, topRow);
-  }
-
-  @Override
-  public void scrollViewToColumnIn(AlignFrame alf, String leftHandColumn)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    appLoader.scrollViewToColumnIn(alf, leftHandColumn);
-  }
-
-  @Override
-  public String getFeatureGroups()
-  {
-    return getFeatureGroupsOn(null);
-  }
-
-  @Override
-  public String getFeatureGroupsOn(AlignFrame alf)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.getFeatureGroupsOn(alf);
-  }
-
-  @Override
-  public String getFeatureGroupsOfState(boolean visible)
-  {
-    return getFeatureGroupsOfStateOn(null, visible);
-  }
-
-  @Override
-  public String getFeatureGroupsOfStateOn(AlignFrame alf, boolean visible)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.getFeatureGroupsOfStateOn(alf, visible);
-  }
-
-  @Override
-  public void setFeatureGroupState(String groups, boolean state)
-  { // JalviewLite API
-    setFeatureGroupStateOn(null, groups, state);
-  }
-
-  @Override
-  public void setFeatureGroupStateOn(AlignFrame alf, String groups,
-          boolean state)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    appLoader.setFeatureGroupStateOn(alf, groups, state);
-  }
-
-  @Override
-  public String getSeparator()
-  {
-    return appLoader.getSeparator();
-  }
-
-  @Override
-  public void setSeparator(String separator)
-  {
-    appLoader.setSeparator(separator);
-  }
-
-  @Override
-  public String getJsMessage(String messageclass, String viewId)
-  {
-    // see http://www.jalview.org/examples/jalviewLiteJs.html
-    return null;
-  }
-
-  /**
-   * Open a new Tree panel on the desktop statically. Params are standard (not
-   * set by Groovy). No dialog is opened.
-   * 
-   * @param af
-   * @param treeType
-   * @param modelName
-   * @return null, or the string "label.you_need_at_least_n_sequences" if number
-   *         of sequences selected is inappropriate
-   */
-  @Override
-  public Object openTreePanel(AlignFrame af, String treeType,
-          String modelName)
-  { // JalviewJS api
-    if (af == null)
-    {
-      af = getCurrentAlignFrame();
-    }
-    return CalculationChooser.openTreePanel(af, treeType, modelName, null);
-  }
-
-  /**
-   * public static method for JalviewJS API to open a PCAPanel without
-   * necessarily using a dialog.
-   * 
-   * @param af
-   * @param modelName
-   * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences"
-   *         if number of sequences selected is inappropriate
-   */
-  @Override
-  public Object openPcaPanel(AlignFrame af, String modelName)
-  {
-    if (af == null)
-    {
-      af = getCurrentAlignFrame();
-    }
-    return CalculationChooser.openPcaPanel(af, modelName, null);
-  }
-
-  @Override
-  public String getSelectedSequencesAsAlignment(String format,
-          boolean suffix)
-  {
-    return getSelectedSequencesAsAlignmentFrom(null, format, suffix);
-  }
-
-  @Override
-  public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
-          String format, boolean suffix)
-  {
-    if (alf == null)
-    {
-      alf = getCurrentAlignFrame();
-    }
-    return appLoader.getSelectedSequencesAsAlignmentFrom(alf, format,
-            "" + suffix);
-  }
-
-  @Override
-  public String arrayToSeparatorList(String[] array)
-  {
-    return appLoader.arrayToSeparatorList(array);
-  }
-
-  @Override
-  public String[] separatorListToArray(String list)
-  {
-    return appLoader.separatorListToArray(list);
-  }
-
-  //// probably not needed in JalviewJS -- From when Jmol and Jalview did not
-  //// have a direct connection?
-
-  @Override
-  public void setMouseoverListener(String listener)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void setMouseoverListener(AlignFrame af, String listener)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void setSelectionListener(String listener)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void setSelectionListener(AlignFrame af, String listener)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void setStructureListener(String listener, String modelSet)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void removeJavascriptListener(AlignFrame af, String listener)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void mouseOverStructure(String pdbResNum, String chain,
-          String pdbfile)
-  {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void showOverview()
-  {
-    currentAlignFrame.overviewMenuItem_actionPerformed(null);
+  public String doSendCallback(Object callback, Object[] data) {
+    return (Platform.isJS() ? app.doSendCallback(callback, data) : null);
   }
 
   public void notifyWorker(AlignCalcWorkerI worker, String status)
@@ -2118,4 +1289,10 @@ public class Jalview implements ApplicationSingletonI, JalviewJSApi
     // + " " + status);
   }
 
+  public Object arrayToSeparatorList(String[] seqs)
+  {
+    return (Platform.isJS() ? app.arrayToSeparatorList(seqs) : null);
+  }
+  
 }
index 26110f8..544f5d7 100644 (file)
@@ -20,16 +20,37 @@ public class JalviewJS2
 
   static {
     /**
-     * @j2sNative
+     * @ could do it this way:
      * 
-     *            J2S.thisApplet.__Info.args =
-     *            ["open","examples/uniref50.fa","features",
-     *            "examples/exampleFeatures.txt"];
+     * j2sNative
+     * 
+     * J2S.thisApplet.__Info.args = [ "open","examples/uniref50.fa",
+     * "features","examples/exampleFeatures.txt", "noannotation" ];
      */
   }
 
   public static void main(String[] args) throws Exception
   {
+    if (args.length == 0)
+    {
+      args = new String[] {
+        //  "headless",
+          "open", "examples/uniref50.fa",
+          "features",
+          "examples/exampleFeatures.txt"
+          , "noannotation"
+          //, "showoverview"
+          //, "png", "test-bh.png"
+      };
+    }
+
+    // String cmds = "nodisplay -open examples/uniref50.fa -sortbytree -props
+    // test/jalview/io/testProps.jvprops -colour zappo "
+    // + "-jabaws http://www.compbio.dundee.ac.uk/jabaws -nosortbytree "
+    // + "-features examples/testdata/plantfdx.features -annotations
+    // examples/testdata/plantfdx.annotations -tree
+    // examples/testdata/uniref50_test_tree";
+    // args = cmds.split(" ");
     Jalview.main(args);
        //showFocusTimer();
 }
index a21bebe..7c9dee8 100644 (file)
@@ -1,6 +1,20 @@
 package jalview.bin;
 
+import java.io.IOException;
+import java.net.URL;
+import java.util.Hashtable;
+
+import jalview.api.AlignViewportI;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
+import jalview.io.DataSourceType;
+import jalview.io.NewickFile;
+import jalview.structure.SelectionSource;
+import jalview.structure.VamsasSource;
 
 /**
  * JAL-3369 JalviewJS API BH 2019.07.17
@@ -11,42 +25,29 @@ import jalview.gui.AlignFrame;
 public interface JalviewJSApi
 {
 
-  void showOverview();
+  // debug flag - controls output to standard out
+  public static boolean debug = false;
 
   /**
-   * process commandline arguments after the JavaScript application has started
+   * bind a pdb file to a sequence in the given AlignFrame.
    * 
-   * @param args
-   * @return
+   * @param alFrame
+   *          - null or specific AlignFrame. This specifies the dataset that
+   *          will be searched for a seuqence called sequenceId
+   * @param sequenceId
+   *          - sequenceId within the dataset.
+   * @param pdbEntryString
+   *          - the short name for the PDB file
+   * @param pdbFile
+   *          - pdb file - either a URL or a valid PDB file.
+   * @return true if binding was as success TODO: consider making an exception
+   *         structure for indicating when PDB parsing or sequenceId location
+   *         fails.
    */
-  Object parseArguments(String[] args);
-
-
-  /**
-   * Open a new Tree panel on the desktop statically. Params are standard (not
-   * set by Groovy). No dialog is opened.
-   * 
-   * @param af
-   *          may be null
-   * @param treeType
-   * @param modelName
-   * @return null, or the string "label.you_need_at_least_n_sequences" if number
-   *         of sequences selected is inappropriate
-   */
-  public Object openTreePanel(AlignFrame af, String treeType,
-          String modelName);
+  public abstract boolean addPdbFile(AlignFrame alFrame, String sequenceId,
+          String pdbEntryString, String pdbFile);
 
-  /**
-   * public static method for JalviewJS API to open a PCAPanel without
-   * necessarily using a dialog.
-   * 
-   * @param af
-   *          may be null
-   * @param modelName
-   * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences"
-   *         if number of sequences selected is inappropriate
-   */
-  public Object openPcaPanel(AlignFrame af, String modelName);
+  public String arrayToSeparatorList(String[] array);
 
   /**
    * The following public methods may be called externally, eg via javascript in
@@ -71,348 +72,230 @@ public interface JalviewJSApi
   // public interface JalviewLiteJsApi
   // {
 
-    /**
-     * @return String list of selected sequence IDs, each terminated by the
-     *         'boolean not' character (""+0x00AC); or (&#172;);
-     */
-
-    public abstract String getSelectedSequences();
-
-    /**
-     * @param sep
-     *          separator string or null for default
-     * @return String list of selected sequence IDs, each terminated by given
-     *         separator string
-     */
-
-    public abstract String getSelectedSequences(String sep);
-
-    /**
-     * @param alf
-     *          AlignFrame containing selection
-     * @return String list of selected sequence IDs, each terminated by current
-     *         default separator sequence
-     * 
-     */
-    public abstract String getSelectedSequencesFrom(AlignFrame alf);
-
-    /**
-     * get list of selected sequence IDs separated by given separator
-     * 
-     * @param alf
-     *          window containing selection
-     * @param sep
-     *          separator string to use - default is 'boolean not'
-     * @return String list of selected sequence IDs, each terminated by the given
-     *         separator
-     */
-    public abstract String getSelectedSequencesFrom(AlignFrame alf,
-            String sep);
-
-    /**
-     * 
-     * @param sequenceId
-     *          id of sequence to highlight
-     * @param position
-     *          integer position [ tobe implemented or range ] on sequence
-     * @param alignedPosition
-     *          true/false/empty string - indicate if position is an alignment
-     *          column or unaligned sequence position
-     */
-
-    public abstract void highlight(String sequenceId, String position,
-            String alignedPosition);
-
-    /**
-     * 
-     * @param sequenceId
-     *          id of sequence to highlight
-     * @param position
-     *          integer position [ tobe implemented or range ] on sequence
-     * @param alignedPosition
-     *          false, blank or something else - indicate if position is an
-     *          alignment column or unaligned sequence position
-     */
-    public abstract void highlightIn(AlignFrame alf, String sequenceId,
-            String position, String alignedPosition);
-
-    /**
-     * select regions of the currrent alignment frame
-     * 
-     * @param sequenceIds
-     *          String separated list of sequence ids or empty string
-     * @param columns
-     *          String separated list { column range or column, ..} or empty
-     *          string
-     */
-
-    public abstract void select(String sequenceIds, String columns);
-
-    /**
-     * select regions of the currrent alignment frame
-     * 
-     * @param toselect
-     *          String separated list { column range, seq1...seqn sequence ids }
-     * @param sep
-     *          separator between toselect fields
-     */
-
-    public abstract void select(String sequenceIds, String columns,
-            String sep);
-
-    /**
-     * select regions of the given alignment frame
-     * 
-     * @param alf
-     * @param toselect
-     *          String separated list { column range, seq1...seqn sequence ids }
-     * @param sep
-     *          separator between toselect fields
-     */
-    public abstract void selectIn(AlignFrame alf, String sequenceIds,
-            String columns);
-
-    /**
-     * select regions of the given alignment frame
-     * 
-     * @param alf
-     * @param toselect
-     *          String separated list { column range, seq1...seqn sequence ids }
-     * @param sep
-     *          separator between toselect fields
-     */
-    public abstract void selectIn(AlignFrame alf, String sequenceIds,
-            String columns, String sep);
-
-    /**
-     * get sequences selected in current AlignFrame and return their alignment in
-     * format 'format' either with or without suffix
-     * 
-     * @param alf
-     *          - where selection is
-     * @param format
-     *          - format of alignment file
-     * @param suffix
-     *          - "true" to append /start-end string to each sequence ID
-     * @return selected sequences as flat file or empty string if there was no
-     *         current selection
-     */
-
-    public abstract String getSelectedSequencesAsAlignment(String format,
-            String suffix);
-
-    /**
-     * get sequences selected in alf and return their alignment in format 'format'
-     * either with or without suffix
-     * 
-     * @param alf
-     *          - where selection is
-     * @param format
-     *          - format of alignment file
-     * @param suffix
-     *          - "true" to append /start-end string to each sequence ID
-     * @return selected sequences as flat file or empty string if there was no
-     *         current selection
-     */
-    public abstract String getSelectedSequencesAsAlignmentFrom(
-            AlignFrame alf,
-            String format, String suffix);
-
-    /**
-     * get a separator separated list of sequence IDs reflecting the order of the
-     * current alignment
-     * 
-     * @return
-     */
-
-    public abstract String getAlignmentOrder();
-
-    /**
-     * get a separator separated list of sequence IDs reflecting the order of the
-     * alignment in alf
-     * 
-     * @param alf
-     * @return
-     */
-    public abstract String getAlignmentOrderFrom(AlignFrame alf);
-
-    /**
-     * get a sep separated list of sequence IDs reflecting the order of the
-     * alignment in alf
-     * 
-     * @param alf
-     * @param sep
-     *          - separator to use
-     * @return
-     */
-    public abstract String getAlignmentOrderFrom(AlignFrame alf,
-            String sep);
-
-    /**
-     * re-order the current alignment using the given list of sequence IDs
-     * 
-     * @param order
-     *          - sep separated list
-     * @param undoName
-     *          - string to use when referring to ordering action in undo buffer
-     * @return 'true' if alignment was actually reordered. empty string if
-     *         alignment did not contain sequences.
-     */
-
-    public abstract String orderBy(String order, String undoName);
-
-    /**
-     * re-order the current alignment using the given list of sequence IDs
-     * separated by sep
-     * 
-     * @param order
-     *          - sep separated list
-     * @param undoName
-     *          - string to use when referring to ordering action in undo buffer
-     * @param sep
-     * @return 'true' if alignment was actually reordered. empty string if
-     *         alignment did not contain sequences.
-     */
-
-    public abstract String orderBy(String order, String undoName,
-            String sep);
-
-    /**
-     * re-order the given alignment using the given list of sequence IDs separated
-     * by sep
-     * 
-     * @param alf
-     * @param order
-     *          - sep separated list
-     * @param undoName
-     *          - string to use when referring to ordering action in undo buffer
-     * @param sep
-     * @return 'true' if alignment was actually reordered. empty string if
-     *         alignment did not contain sequences.
-     */
-    public abstract String orderAlignmentBy(AlignFrame alf, String order,
-            String undoName, String sep);
-
-    /**
-     * get alignment as format (format names FASTA, BLC, CLUSTAL, MSF, PILEUP,
-     * PFAM - see jalview.io.AppletFormatAdapter for full list);
-     * 
-     * @param format
-     * @return
-     */
-
-    public abstract String getAlignment(String format);
-
-    /**
-     * get alignment displayed in alf as format
-     * 
-     * @param alf
-     * @param format
-     * @return
-     */
-    public abstract String getAlignmentFrom(AlignFrame alf, String format);
-
-    /**
-     * get alignment as format with jalview start-end sequence suffix appended
-     * 
-     * @param format
-     * @param suffix
-     * @return
-     */
-
-    public abstract String getAlignment(String format, String suffix);
-
-    /**
-     * get alignment displayed in alf as format with or without the jalview
-     * start-end sequence suffix appended
-     * 
-     * @param alf
-     * @param format
-     * @param suffix
-     * @return
-     */
-    public abstract String getAlignmentFrom(AlignFrame alf, String format,
-            String suffix);
-
-    /**
-     * add the given features or annotation to the current alignment
-     * 
-     * @param annotation
-     */
-
-    public abstract void loadAnnotation(String annotation);
-
-    /**
-     * add the given features or annotation to the given alignment view
-     * 
-     * @param alf
-     * @param annotation
-     */
-    public abstract void loadAnnotationFrom(AlignFrame alf,
-            String annotation);
-
-    /**
-     * parse the given string as a jalview feature or GFF annotation file and
-     * optionally enable feature display on the current AlignFrame
-     * 
-     * @param features
-     *          - gff or features file
-     * @param autoenabledisplay
-     *          - when true, feature display will be enabled if any features can
-     *          be parsed from the string.
-     */
-
-    public abstract void loadFeatures(String features,
-            boolean autoenabledisplay);
-
-    /**
-     * parse the given string as a jalview feature or GFF annotation file and
-     * optionally enable feature display on the given AlignFrame.
-     * 
-     * @param alf
-     * @param features
-     *          - gff or features file
-     * @param autoenabledisplay
-     *          - when true, feature display will be enabled if any features can
-     *          be parsed from the string.
-     * @return true if data parsed as features
-     */
-    public abstract boolean loadFeaturesFrom(AlignFrame alf, String features,
-            boolean autoenabledisplay);
-
-    /**
-     * get the sequence features in the given format (Jalview or GFF);
-     * 
-     * @param format
-     * @return
-     */
-
-    public abstract String getFeatures(String format);
-
-    /**
-     * get the sequence features in alf in the given format (Jalview or GFF);
-     * 
-     * @param alf
-     * @param format
-     * @return
-     */
-    public abstract String getFeaturesFrom(AlignFrame alf, String format);
-
-    /**
-     * get current alignment's annotation as an annotation file
-     * 
-     * @return
-     */
-
-    public abstract String getAnnotation();
-
-    /**
-     * get alignment view alf's annotation as an annotation file
-     * 
-     * @param alf
-     * @return
-     */
-    public abstract String getAnnotationFrom(AlignFrame alf);
+  /**
+   * get alignment as format (format names FASTA, BLC, CLUSTAL, MSF, PILEUP,
+   * PFAM - see jalview.io.AppletFormatAdapter for full list);
+   * 
+   * @param format
+   * @return
+   */
+
+  public abstract String getAlignment(String format);
+
+  /**
+   * get alignment as format with jalview start-end sequence suffix appended
+   * 
+   * @param format
+   * @param suffix
+   * @return
+   */
+
+  public abstract String getAlignment(String format, String suffix);
+
+  /**
+   * get alignment displayed in alf as format
+   * 
+   * @param alf
+   * @param format
+   * @return
+   */
+  public abstract String getAlignmentFrom(AlignFrame alf, String format);
+
+  /**
+   * get alignment displayed in alf as format with or without the jalview
+   * start-end sequence suffix appended
+   * 
+   * @param alf
+   * @param format
+   * @param suffix
+   * @return
+   */
+  public abstract String getAlignmentFrom(AlignFrame alf, String format,
+          String suffix);
+
+  /**
+   * get a separator separated list of sequence IDs reflecting the order of the
+   * current alignment
+   * 
+   * @return
+   */
+
+  public abstract String getAlignmentOrder();
+
+  /**
+   * get a separator separated list of sequence IDs reflecting the order of the
+   * alignment in alf
+   * 
+   * @param alf
+   * @return
+   */
+  public abstract String getAlignmentOrderFrom(AlignFrame alf);
+
+  /**
+   * get a sep separated list of sequence IDs reflecting the order of the
+   * alignment in alf
+   * 
+   * @param alf
+   * @param sep
+   *          - separator to use
+   * @return
+   */
+  public abstract String getAlignmentOrderFrom(AlignFrame alf, String sep);
+
+  /**
+   * get current alignment's annotation as an annotation file
+   * 
+   * @return
+   */
+
+  public abstract String getAnnotation();
+
+  /**
+   * get alignment view alf's annotation as an annotation file
+   * 
+   * @param alf
+   * @return
+   */
+  public abstract String getAnnotationFrom(AlignFrame alf);
+
+  public Object getAppletParameter(String name, boolean asString);
+
+  public URL getCodeBase();
+
+  public URL getDocumentBase();
+
+  /**
+   * 
+   * @return
+   * @see jalview.appletgui.AlignFrame#getFeatureGroups();
+   */
+
+  public abstract String getFeatureGroups();
+
+  /**
+   * @param visible
+   * @return
+   * @see jalview.appletgui.AlignFrame#getFeatureGroupsOfState(boolean);
+   */
+
+  public abstract String getFeatureGroupsOfState(boolean visible);
+
+  /**
+   * @param alf
+   *          align frame to get groups of state visible
+   * @param visible
+   * @return
+   * @see jalview.appletgui.AlignFrame#getFeatureGroupsOfState(boolean);
+   */
+  public abstract String getFeatureGroupsOfStateOn(AlignFrame alf,
+          boolean visible);
+
+  /**
+   * @param alf
+   *          AlignFrame to get feature groups on
+   * @return
+   * @see jalview.appletgui.AlignFrame#getFeatureGroups();
+   */
+  public abstract String getFeatureGroupsOn(AlignFrame alf);
+
+  /**
+   * get the sequence features in the given format (Jalview or GFF);
+   * 
+   * @param format
+   * @return
+   */
+
+  public abstract String getFeatures(String format);
+
+  /**
+   * get the sequence features in alf in the given format (Jalview or GFF);
+   * 
+   * @param alf
+   * @param format
+   * @return
+   */
+  public abstract String getFeaturesFrom(AlignFrame alf, String format);
+
+  public Object getFrameForSource(VamsasSource source);
+
+  public Hashtable<String, int[]> getJSHashes();
+
+  /**
+   * Retrieve fragments of a large packet of data made available by JalviewLite.
+   * 
+   * @param messageclass
+   * @param viewId
+   * @return next chunk of message
+   */
+
+  public abstract String getJsMessage(String messageclass, String viewId);
+
+  Hashtable<String, Hashtable<String, String[]>> getJSMessages();
+
+  public Object getJSObject();
+
+  public jalview.renderer.seqfeatures.FeatureRenderer getNewFeatureRenderer(
+          AlignViewportI vp);
+
+  public String getParameter(String name);
+
+  /**
+   * @return String list of selected sequence IDs, each terminated by the
+   *         'boolean not' character (""+0x00AC); or (&#172;);
+   */
+
+  public abstract String getSelectedSequences();
+
+  /**
+   * @param sep
+   *          separator string or null for default
+   * @return String list of selected sequence IDs, each terminated by given
+   *         separator string
+   */
+
+  public abstract String getSelectedSequences(String sep);
+
+  /**
+   * get sequences selected in current AlignFrame and return their alignment in
+   * format 'format' either with or without suffix
+   * 
+   * @param alf
+   *          - where selection is
+   * @param format
+   *          - format of alignment file
+   * @param suffix
+   *          - "true" to append /start-end string to each sequence ID
+   * @return selected sequences as flat file or empty string if there was no
+   *         current selection
+   */
+
+  public abstract String getSelectedSequencesAsAlignment(String format,
+          String suffix);
+
+  /**
+   * get sequences selected in alf and return their alignment in format 'format'
+   * either with or without suffix
+   * 
+   * @param alf
+   *          - where selection is
+   * @param format
+   *          - format of alignment file
+   * @param suffix
+   *          - "true" to append /start-end string to each sequence ID
+   * @return selected sequences as flat file or empty string if there was no
+   *         current selection
+   */
+  public abstract String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
+          String format, String suffix);
+
+  /**
+   * @param alf
+   *          AlignFrame containing selection
+   * @return String list of selected sequence IDs, each terminated by current
+   *         default separator sequence
+   * 
+   */
+  public abstract String getSelectedSequencesFrom(AlignFrame alf);
 
   // BH incompatibility here -- JalviewLite created an AlignFrame; Jalview
   // creates an AlignmentPanel
@@ -450,244 +333,352 @@ public interface JalviewJSApi
   // */
   // public abstract AlignFrame newViewFrom(AlignFrame alf, String name);
 
-    /**
-     * 
-     * @param text
-     *          alignment file as a string
-     * @param title
-     *          window title
-     * @return null or new alignment frame
-     */
-
-    public abstract AlignFrame loadAlignment(String text, String title);
-
-    /**
-     * register a javascript function to handle any alignment mouseover events
-     * 
-     * @param listener
-     *          name of javascript function (called with arguments
-     *          [jalview.appletgui.AlignFrame,String(sequence id);,String(column
-     *          in alignment);, String(position in sequence);]
-     */
-
-    public abstract void setMouseoverListener(String listener);
-
-    /**
-     * register a javascript function to handle mouseover events
-     * 
-     * @param af
-     *          (null or specific AlignFrame for which events are to be listened
-     *          for);
-     * @param listener
-     *          name of javascript function
-     */
-    public abstract void setMouseoverListener(AlignFrame af,
-            String listener);
-
-    /**
-     * register a javascript function to handle any alignment selection events.
-     * Events are generated when the user completes a selection event, or when the
-     * user deselects all selected regions.
-     * 
-     * @param listener
-     *          name of javascript function (called with arguments
-     *          [jalview.appletgui.AlignFrame, String(sequence set id);,
-     *          String(separator separated list of sequences which were
-     *          selected);, String(separator separated list of column ranges (i.e.
-     *          single number or hyphenated range); that were selected);]
-     */
-
-    public abstract void setSelectionListener(String listener);
-
-    public abstract void setSelectionListener(AlignFrame af,
-            String listener);
-
-    /**
-     * register a javascript function to handle events normally routed to a Jmol
-     * structure viewer.
-     * 
-     * @param listener
-     *          - javascript function (arguments are variable, see
-     *          jalview.javascript.MouseOverStructureListener for full details);
-     * @param modelSet
-     *          - separator separated list of PDB file URIs that this viewer is
-     *          handling. These files must be in the same order they appear in
-     *          Jmol (e.g. first one is frame 1, second is frame 2, etc);.
-     * @see jalview.javascript.MouseOverStructureListener
-     */
-
-    public abstract void setStructureListener(String listener,
-            String modelSet);
-
-    /**
-     * remove any callback using the given listener function and associated with
-     * the given AlignFrame (or null for all callbacks);
-     * 
-     * @param af
-     *          (may be null);
-     * @param listener
-     *          (may be null);
-     */
-    public abstract void removeJavascriptListener(AlignFrame af,
-            String listener);
-
-    /**
-     * send a mouseover message to all the alignment windows associated with the
-     * given residue in the pdbfile
-     * 
-     * @param pdbResNum
-     * @param chain
-     * @param pdbfile
-     */
-
-    public abstract void mouseOverStructure(String pdbResNum, String chain,
-            String pdbfile);
-
-    /**
-     * bind a pdb file to a sequence in the given AlignFrame.
-     * 
-     * @param alFrame
-     *          - null or specific AlignFrame. This specifies the dataset that
-     *          will be searched for a seuqence called sequenceId
-     * @param sequenceId
-     *          - sequenceId within the dataset.
-     * @param pdbEntryString
-     *          - the short name for the PDB file
-     * @param pdbFile
-     *          - pdb file - either a URL or a valid PDB file.
-     * @return true if binding was as success TODO: consider making an exception
-     *         structure for indicating when PDB parsing or sequenceId location
-     *         fails.
-     */
-    public abstract boolean addPdbFile(AlignFrame alFrame, String sequenceId,
-            String pdbEntryString, String pdbFile);
-
-    /**
-     * adjust horizontal/vertical scroll to make the given location the top left
-     * hand corner for the given view
-     * 
-     * @param alf
-     * @param topRow
-     * @param leftHandColumn
-     */
-    public abstract void scrollViewToIn(AlignFrame alf, String topRow,
-            String leftHandColumn);
-
-    /**
-     * adjust vertical scroll to make the given row the top one for given view
-     * 
-     * @param alf
-     * @param topRow
-     */
-    public abstract void scrollViewToRowIn(AlignFrame alf, String topRow);
-
-    /**
-     * adjust horizontal scroll to make the given column the left one in the given
-     * view
-     * 
-     * @param alf
-     * @param leftHandColumn
-     */
-    public abstract void scrollViewToColumnIn(AlignFrame alf,
-            String leftHandColumn);
-
-    /**
-     * 
-     * @return
-     * @see jalview.appletgui.AlignFrame#getFeatureGroups();
-     */
-
-    public abstract String getFeatureGroups();
-
-    /**
-     * @param alf
-     *          AlignFrame to get feature groups on
-     * @return
-     * @see jalview.appletgui.AlignFrame#getFeatureGroups();
-     */
-    public abstract String getFeatureGroupsOn(AlignFrame alf);
-
-    /**
-     * @param visible
-     * @return
-     * @see jalview.appletgui.AlignFrame#getFeatureGroupsOfState(boolean);
-     */
-
-    public abstract String getFeatureGroupsOfState(boolean visible);
-
-    /**
-     * @param alf
-     *          align frame to get groups of state visible
-     * @param visible
-     * @return
-     * @see jalview.appletgui.AlignFrame#getFeatureGroupsOfState(boolean);
-     */
-    public abstract String getFeatureGroupsOfStateOn(AlignFrame alf,
-            boolean visible);
-
-    /**
-     * @param groups
-     *          tab separated list of group names
-     * @param state
-     *          true or false
-     * @see jalview.appletgui.AlignFrame#setFeatureGroupState(java.lang.String[],
-     *      boolean);
-     */
-    public abstract void setFeatureGroupStateOn(AlignFrame alf,
-            String groups,
-            boolean state);
-
-
-    public abstract void setFeatureGroupState(String groups, boolean state);
-
-    /**
-     * List separator string
-     * 
-     * @return the separator
-     */
-
-    public abstract String getSeparator();
-
-    /**
-     * List separator string
-     * 
-     * @param separator
-     *          the separator to set. empty string will reset separator to default
-     */
-
-    public abstract void setSeparator(String separator);
-
-    /**
-     * Retrieve fragments of a large packet of data made available by JalviewLite.
-     * 
-     * @param messageclass
-     * @param viewId
-     * @return next chunk of message
-     */
-
-    public abstract String getJsMessage(String messageclass, String viewId);
-
-    /// in http://www.jalview.org/examples/jalviewLiteJs.html but missing here
-
-    // get selected sequences as alignment as format with or without start-end
-    // suffix
-
-    public String getSelectedSequencesAsAlignment(String format,
-            boolean suffix);
-
-    // get selected sequences as alignment from given view as format with or
-    // without start-end suffix
-    public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
-            String format, boolean suffix);
-
-
-    public String arrayToSeparatorList(String[] array);
-
-    // get a string array from a list
-
-    public String[] separatorListToArray(String list);
-
-    // debug flag - controls output to standard out
-    public static boolean debug = false;
+  /**
+   * get list of selected sequence IDs separated by given separator
+   * 
+   * @param alf
+   *          window containing selection
+   * @param sep
+   *          separator string to use - default is 'boolean not'
+   * @return String list of selected sequence IDs, each terminated by the given
+   *         separator
+   */
+  public abstract String getSelectedSequencesFrom(AlignFrame alf,
+          String sep);
+
+  public Object[] getSelectionForListener(SequenceGroup seqsel,
+          ColumnSelection colsel, HiddenColumns hidden,
+          SelectionSource source, Object alignFrame);
+
+  /**
+   * List separator string
+   * 
+   * @return the separator
+   */
+
+  public abstract String getSeparator();
+
+  public AlignViewportI getViewport();
+
+  /**
+   * 
+   * @param sequenceId
+   *          id of sequence to highlight
+   * @param position
+   *          integer position [ tobe implemented or range ] on sequence
+   * @param alignedPosition
+   *          true/false/empty string - indicate if position is an alignment
+   *          column or unaligned sequence position
+   */
+
+  public abstract void highlight(String sequenceId, String position,
+          String alignedPosition);
+
+  /**
+   * 
+   * @param sequenceId
+   *          id of sequence to highlight
+   * @param position
+   *          integer position [ tobe implemented or range ] on sequence
+   * @param alignedPosition
+   *          false, blank or something else - indicate if position is an
+   *          alignment column or unaligned sequence position
+   */
+  public abstract void highlightIn(AlignFrame alf, String sequenceId,
+          String position, String alignedPosition);
+
+  /**
+   * 
+   * @param text
+   *          alignment file as a string
+   * @param title
+   *          window title
+   * @return null or new alignment frame
+   */
+
+  public abstract AlignFrame loadAlignment(String text, String title);
+
+  /**
+   * add the given features or annotation to the current alignment
+   * 
+   * @param annotation
+   */
+
+  public abstract void loadAnnotation(String annotation);
+
+  /**
+   * add the given features or annotation to the given alignment view
+   * 
+   * @param alf
+   * @param annotation
+   */
+  public abstract void loadAnnotationFrom(AlignFrame alf,
+          String annotation);
+
+  /**
+   * parse the given string as a jalview feature or GFF annotation file and
+   * optionally enable feature display on the current AlignFrame
+   * 
+   * @param features
+   *          - gff or features file
+   * @param autoenabledisplay
+   *          - when true, feature display will be enabled if any features can
+   *          be parsed from the string.
+   */
+
+  public abstract void loadFeatures(String features,
+          boolean autoenabledisplay);
+
+  /**
+   * parse the given string as a jalview feature or GFF annotation file and
+   * optionally enable feature display on the given AlignFrame.
+   * 
+   * @param alf
+   * @param features
+   *          - gff or features file
+   * @param autoenabledisplay
+   *          - when true, feature display will be enabled if any features can
+   *          be parsed from the string.
+   * @return true if data parsed as features
+   */
+  public abstract boolean loadFeaturesFrom(AlignFrame alf, String features,
+          boolean autoenabledisplay);
+
+  public boolean loadScoreFile(String sScoreFile) throws IOException;
+
+  public void newFeatureSettings();
+
+  public void newStructureView(PDBEntry pdb, SequenceI[] seqs,
+          String[] chains, DataSourceType protocol);
+
+  /**
+   * public static method for JalviewJS API to open a PCAPanel without
+   * necessarily using a dialog.
+   * 
+   * @param af
+   *          may be null
+   * @param modelName
+   * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences"
+   *         if number of sequences selected is inappropriate
+   */
+  public Object openPcaPanel(AlignFrame af, String modelName);
+
+  /**
+   * Open a new Tree panel on the desktop statically. Params are standard (not
+   * set by Groovy). No dialog is opened.
+   * 
+   * @param af
+   *          may be null
+   * @param treeType
+   * @param modelName
+   * @return null, or the string "label.you_need_at_least_n_sequences" if number
+   *         of sequences selected is inappropriate
+   */
+  public Object openTreePanel(AlignFrame af, String treeType,
+          String modelName);
+
+  /// in http://www.jalview.org/examples/jalviewLiteJs.html but missing here
+
+  // get selected sequences as alignment as format with or without start-end
+  // suffix
+
+  /**
+   * re-order the given alignment using the given list of sequence IDs separated
+   * by sep
+   * 
+   * @param alf
+   * @param order
+   *          - sep separated list
+   * @param undoName
+   *          - string to use when referring to ordering action in undo buffer
+   * @param sep
+   * @return 'true' if alignment was actually reordered. empty string if
+   *         alignment did not contain sequences.
+   */
+  public abstract String orderAlignmentBy(AlignFrame alf, String order,
+          String undoName, String sep);
+
+  // get a string array from a list
+
+  /**
+   * re-order the current alignment using the given list of sequence IDs
+   * 
+   * @param order
+   *          - sep separated list
+   * @param undoName
+   *          - string to use when referring to ordering action in undo buffer
+   * @return 'true' if alignment was actually reordered. empty string if
+   *         alignment did not contain sequences.
+   */
+
+  public abstract String orderBy(String order, String undoName);
+
+  /**
+   * re-order the current alignment using the given list of sequence IDs
+   * separated by sep
+   * 
+   * @param order
+   *          - sep separated list
+   * @param undoName
+   *          - string to use when referring to ordering action in undo buffer
+   * @param sep
+   * @return 'true' if alignment was actually reordered. empty string if
+   *         alignment did not contain sequences.
+   */
+
+  public abstract String orderBy(String order, String undoName, String sep);
+
+  /**
+   * process commandline arguments after the JavaScript application has started
+   * 
+   * @param args
+   * @return
+   */
+  Object parseArguments(String[] args);
+
+  // public boolean getDefaultParameter(String name, boolean def);
+
+  public boolean parseFeaturesFile(String param, DataSourceType protocol);
+
+  /**
+   * remove any callback using the given listener function and associated with
+   * the given AlignFrame (or null for all callbacks);
+   * 
+   * @param af
+   *          (may be null);
+   * @param listener
+   *          (may be null);
+   */
+  public abstract void removeSelectionListener(AlignFrame af,
+          String listener);
+
+  // public void setAlignPdbStructures(boolean defaultParameter);
+
+  /**
+   * adjust horizontal scroll to make the given column the left one in the given
+   * view
+   * 
+   * @param alf
+   * @param leftHandColumn
+   */
+  public abstract void scrollViewToColumnIn(AlignFrame alf,
+          String leftHandColumn);
+
+  /**
+   * adjust horizontal/vertical scroll to make the given location the top left
+   * hand corner for the given view
+   * 
+   * @param alf
+   * @param topRow
+   * @param leftHandColumn
+   */
+  public abstract void scrollViewToIn(AlignFrame alf, String topRow,
+          String leftHandColumn);
+
+  /**
+   * adjust vertical scroll to make the given row the top one for given view
+   * 
+   * @param alf
+   * @param topRow
+   */
+  public abstract void scrollViewToRowIn(AlignFrame alf, String topRow);
+
+  /**
+   * select regions of the currrent alignment frame
+   * 
+   * @param sequenceIds
+   *          String separated list of sequence ids or empty string
+   * @param columns
+   *          String separated list { column range or column, ..} or empty
+   *          string
+   */
+
+  public abstract void select(String sequenceIds, String columns);
+
+  /**
+   * select regions of the currrent alignment frame
+   * 
+   * @param toselect
+   *          String separated list { column range, seq1...seqn sequence ids }
+   * @param sep
+   *          separator between toselect fields
+   */
+
+  public abstract void select(String sequenceIds, String columns,
+          String sep);
+
+  /**
+   * select regions of the given alignment frame
+   * 
+   * @param alf
+   * @param toselect
+   *          String separated list { column range, seq1...seqn sequence ids }
+   * @param sep
+   *          separator between toselect fields
+   */
+  public abstract void selectIn(AlignFrame alf, String sequenceIds,
+          String columns);
+
+  /**
+   * select regions of the given alignment frame
+   * 
+   * @param alf
+   * @param toselect
+   *          String separated list { column range, seq1...seqn sequence ids }
+   * @param sep
+   *          separator between toselect fields
+   */
+  public abstract void selectIn(AlignFrame alf, String sequenceIds,
+          String columns, String sep);
+
+  public String[] separatorListToArray(String list);
+
+  public abstract void setFeatureGroupState(String groups, boolean state);
+
+  public void setFeatureGroupState(String[] groups, boolean state);
+
+  // public StructureSelectionManagerProvider
+  // getStructureSelectionManagerProvider();
+
+  /**
+   * @param groups
+   *          tab separated list of group names
+   * @param state
+   *          true or false
+   * @see jalview.appletgui.AlignFrame#setFeatureGroupState(java.lang.String[],
+   *      boolean);
+   */
+  public abstract void setFeatureGroupStateOn(AlignFrame alf, String groups,
+          boolean state);
+
+  public abstract void setSelectionListener(AlignFrame af, String listener);
+
+  /**
+   * register a javascript function to handle any alignment selection events.
+   * Events are generated when the user completes a selection event, or when the
+   * user deselects all selected regions.
+   * 
+   * @param listener
+   *          name of javascript function (called with arguments
+   *          [jalview.appletgui.AlignFrame, String(sequence set id);,
+   *          String(separator separated list of sequences which were
+   *          selected);, String(separator separated list of column ranges (i.e.
+   *          single number or hyphenated range); that were selected);]
+   */
+
+  public abstract void setSelectionListener(String listener);
+
+  /**
+   * List separator string
+   * 
+   * @param separator
+   *          the separator to set. empty string will reset separator to default
+   */
+
+  public abstract void setSeparator(String separator);
+
+  void showOverview();
+
+  public void updateForAnnotations();
 
 }
index e7f2a53..6a8db59 100644 (file)
@@ -45,10 +45,12 @@ import jalview.io.IdentifyFile;
 import jalview.io.JPredFile;
 import jalview.io.JnetAnnotationMaker;
 import jalview.io.NewickFile;
-import jalview.javascript.JSFunctionExec;
-import jalview.javascript.JalviewLiteJsApi;
-import jalview.javascript.JsCallBack;
-import jalview.javascript.MouseOverStructureListener;
+import jalview.appletgui.js.JSFunctionExec;
+import jalview.appletgui.js.JalviewLiteJsApi;
+import jalview.appletgui.js.JsCallBack;
+import jalview.appletgui.js.JsSelectionSender;
+import jalview.appletgui.js.MouseOverListener;
+import jalview.appletgui.js.MouseOverStructureListener;
 import jalview.structure.SelectionListener;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.ColorUtils;
@@ -920,7 +922,7 @@ public class JalviewLite extends Applet
     setMouseoverListener(currentAlignFrame, listener);
   }
 
-  private Vector<jalview.javascript.JSFunctionExec> javascriptListeners = new Vector<>();
+  private Vector<JSFunctionExec> javascriptListeners = new Vector<>();
 
   /*
    * (non-Javadoc)
@@ -942,7 +944,7 @@ public class JalviewLite extends Applet
         return;
       }
     }
-    jalview.javascript.MouseOverListener mol = new jalview.javascript.MouseOverListener(
+    MouseOverListener mol = new MouseOverListener(
             this, af, listener);
     javascriptListeners.addElement(mol);
     StructureSelectionManager.getStructureSelectionManager(this)
@@ -989,7 +991,7 @@ public class JalviewLite extends Applet
         return;
       }
     }
-    jalview.javascript.JsSelectionSender mol = new jalview.javascript.JsSelectionSender(
+    JsSelectionSender mol = new JsSelectionSender(
             this, af, listener);
     javascriptListeners.addElement(mol);
     StructureSelectionManager.getStructureSelectionManager(this)
@@ -1128,7 +1130,7 @@ public class JalviewLite extends Applet
     {
       while (javascriptListeners.size() > 0)
       {
-        jalview.javascript.JSFunctionExec mol = javascriptListeners
+        JSFunctionExec mol = javascriptListeners
                 .elementAt(0);
         javascriptListeners.removeElement(mol);
         if (mol instanceof SelectionListener)
@@ -1155,7 +1157,7 @@ public class JalviewLite extends Applet
     StructureSelectionManager.release(this);
   }
 
-  private jalview.javascript.JSFunctionExec jsFunctionExec;
+  private JSFunctionExec jsFunctionExec;
 
   /*
    * (non-Javadoc)
@@ -1230,7 +1232,7 @@ public class JalviewLite extends Applet
    * (non-Javadoc)
    * 
    * @see
-   * jalview.javascript.JalviewLiteJsApi#scrollViewToRowIn(jalview.appletgui
+   * JalviewLiteJsApi#scrollViewToRowIn(jalview.appletgui
    * .AlignFrame, java.lang.String)
    */
   @Override
@@ -1261,7 +1263,7 @@ public class JalviewLite extends Applet
    * (non-Javadoc)
    * 
    * @see
-   * jalview.javascript.JalviewLiteJsApi#scrollViewToColumnIn(jalview.appletgui
+   * JalviewLiteJsApi#scrollViewToColumnIn(jalview.appletgui
    * .AlignFrame, java.lang.String)
    */
   @Override
index 453152e..cfb30b3 100644 (file)
@@ -1368,7 +1368,9 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
             htmlName + ((Object) this).toString(), documentBase, codeBase,
             commandOptions, this);
 
-    viewer.setJmolStatusListener(this); // extends JmolCallbackListener
+    viewer.setJmolStatusListener(this); 
+    
+    // BH how about extending Jmol's status listener? 
 
     try
     {
index 815b5ef..6eb2dfe 100644 (file)
@@ -1412,11 +1412,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     bjs.exportHTML(null);
   }
 
-  public void createImageMap(File file, String image)
-  {
-    alignPanel.makePNGImageMap(file, image);
-  }
-
   /**
    * Creates a PNG image of the alignment and writes it to the given file. If
    * the file is null, the user is prompted to choose a file.
index 68313e1..423c62a 100644 (file)
@@ -2324,7 +2324,7 @@ public class Desktop extends GDesktop
   {
     if (Jalview.isHeadlessMode())
     {
-      return new AlignFrame[] { Jalview.currentAlignFrame };
+      return new AlignFrame[] { Jalview.getInstance().currentAlignFrame };
     }
 
     JInternalFrame[] frames =  getDesktopPane().getAllFrames();
index 84fda34..9303aed 100644 (file)
@@ -4326,6 +4326,12 @@ public class Jalview2XML
                   tree.getTitle(), safeInt(tree.getWidth()),
                   safeInt(tree.getHeight()), safeInt(tree.getXpos()),
                   safeInt(tree.getYpos()));
+          if (tp == null)
+          {
+            warn("There was a problem recovering stored Newick tree: \n"
+                    + tree.getNewick());
+            continue;
+          }
           if (tree.getId() != null)
           {
             // perhaps bind the tree id to something ?
@@ -4346,13 +4352,6 @@ public class Jalview2XML
           tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
         }
         tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
-        if (tp == null)
-        {
-          warn("There was a problem recovering stored Newick tree: \n"
-                  + tree.getNewick());
-          continue;
-        }
-
         tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
         tp.fitToWindow_actionPerformed(null);
 
index bb1bb94..636a460 100644 (file)
@@ -1307,7 +1307,11 @@ public class StructureSelectionManager implements ApplicationSingletonI
     }
   }
 
-  public void addSelectionListener(SelectionListener selecter)
+  public List<SelectionListener> getListeners() {
+    return sel_listeners;
+  }
+  
+   public void addSelectionListener(SelectionListener selecter)
   {
     if (!sel_listeners.contains(selecter))
     {
index cd24432..f4ac16f 100644 (file)
@@ -37,6 +37,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Date;
+import java.util.Map;
 import java.util.Properties;
 import java.util.logging.ConsoleHandler;
 import java.util.logging.Level;
@@ -905,5 +906,9 @@ public class Platform
     return failValue;
   }
 
+  public static Map<String, Object> getAppletInfoAsMap()
+  {
+    return (isJS ? jsutil.getAppletInfoAsMap() : null);
+  }
 
 }
index 1b6ff9b..cc4f8d4 100644 (file)
@@ -7,6 +7,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URL;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.Properties;
 import java.util.function.Function;
 import java.util.zip.ZipEntry;
@@ -91,10 +92,10 @@ public interface JSUtilI {
 
 
        /**
-        * Get an attribute of applet's Info map for the applet found using
-        * getApplet(null). That is, applet.__Info[InfoKey].
+        * Get the applet's __Info map or an attribute of that map for the applet found using
+        * getApplet(null). That is, applet.__Info or applet.__Info[InfoKey].
         * 
-        * @param infoKey
+        * @param infoKey if null, return the full __Info map
         */
        Object getAppletInfo(String infoKey);
 
@@ -329,4 +330,22 @@ public interface JSUtilI {
         */
        void setUIEnabled(JComponent jc, boolean enabled);
 
+
+       /**
+        * Play an audio
+        * @param buffer
+        * @param format a javax.sound.sampled.AudioFormat
+        * @throws Exception 
+        */
+       void playAudio(byte[] buffer, Object format) throws Exception;
+
+       /**
+        * For either an applet or an application, get the ORIGINAL __Info as a Map that
+        * has a full set up lower-case keys along with whatever non-all-lower-case keys
+        * provided at start-up.
+        * 
+        * @return
+        */
+       Map<String, Object> getAppletInfoAsMap();
+
 }
diff --git a/unused/JalviewAppLoader.java b/unused/JalviewAppLoader.java
new file mode 100644 (file)
index 0000000..0f4833c
--- /dev/null
@@ -0,0 +1,27 @@
+package jalview.bin;
+
+import java.io.File;
+import java.net.URISyntaxException;
+
+import jalview.gui.AlignFrame;
+import jalview.io.BioJsHTMLOutput;
+import jalview.io.FileFormatI;
+import jalview.io.HtmlSvgOutput;
+import jalview.util.Platform;
+
+/**
+ * Abandoned -- see JalviewApp
+ * 
+ * A class to load parameters for either JalviewLite or Jalview
+ * 
+ * @author hansonr
+ *
+ */
+public class JalviewAppLoader
+{
+  
+  public JalviewAppLoader()
+  {
+  }
+
+}
\ No newline at end of file
diff --git a/unused/JalviewJSApp.java b/unused/JalviewJSApp.java
new file mode 100644 (file)
index 0000000..654569d
--- /dev/null
@@ -0,0 +1,12 @@
+package jalview.bin;
+
+import java.util.List;
+
+import jalview.appletgui.js.JSFunctionExec;
+
+public interface JalviewJSApp
+{
+
+
+
+}