Merge branch 'alpha/origin_2022_JAL-3066_Jalview_212_slivka-integration' into spike...
[jalview.git] / src / jalview / bin / Jalview.java
index a3f934c..eca8147 100755 (executable)
@@ -20,6 +20,8 @@
  */
 package jalview.bin;
 
+import java.awt.GraphicsEnvironment;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -37,35 +39,28 @@ import java.security.PermissionCollection;
 import java.security.Permissions;
 import java.security.Policy;
 import java.util.HashMap;
-import java.util.Hashtable;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Vector;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
-import javax.swing.LookAndFeel;
 import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
 
 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.datamodel.ColumnSelection;
-import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
+import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
 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;
@@ -78,17 +73,13 @@ 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.ChannelProperties;
+import jalview.util.HttpUtils;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.ws.jws2.Jws2Discoverer;
-import netscape.javascript.JSObject;
 
 /**
  * Main class for Jalview Application <br>
@@ -105,30 +96,43 @@ import netscape.javascript.JSObject;
  * @author $author$
  * @version $Revision$
  */
-public class Jalview implements JalviewJSApi
+public class Jalview implements ApplicationSingletonI
 {
-  static
+  // for testing those nasty messages you cannot ever find.
+  // static
+  // {
+  // System.setOut(new PrintStream(new ByteArrayOutputStream())
+  // {
+  // @Override
+  // public void println(Object o)
+  // {
+  // if (o != null)
+  // {
+  // System.err.println(o);
+  // }
+  // }
+  //
+  // });
+  // }
+  public static Jalview getInstance()
   {
-    Platform.getURLCommandArguments();
+    return (Jalview) ApplicationSingletonProvider
+            .getInstance(Jalview.class);
   }
 
-  private boolean headless;
-
-  // singleton instance of this class
+  private Jalview()
+  {
+    Platform.getURLCommandArguments();
+  }
 
-  private static Jalview instance;
 
   private Desktop desktop;
 
-  public static AlignFrame currentAlignFrame;
-
-  public boolean isJavaAppletTag;
+  public AlignFrame currentAlignFrame;
 
   public String appletResourcePath;
 
-  JalviewAppLoader appLoader;
-
-  protected JSFunctionExec jsFunctionExec;
+  public String j2sAppletID;
 
   private boolean noCalculation, noMenuBar, noStatus;
 
@@ -241,12 +245,6 @@ public class Jalview implements JalviewJSApi
 
   }
 
-  public static Jalview getInstance()
-  {
-    return instance;
-  }
-  
-  
   private final static boolean doPlatformLogging = false;
 
   /**
@@ -262,9 +260,12 @@ public class Jalview implements JalviewJSApi
       Platform.startJavaLogging();
     }
 
-    instance = new Jalview();
-    instance.doMain(args);
+    getInstance().doMain(args);
+
   }
+  
+
+  
 
   /**
    * @param args
@@ -273,15 +274,16 @@ public class Jalview implements JalviewJSApi
   {
 
     boolean isJS = Platform.isJS();
-    if (isJS)
-    {
-      Platform.setAppClass(this);
-    }
-    else
+    if (!isJS)
     {
       System.setSecurityManager(null);
     }
 
+    /*
+     * @j2sNative J2S.db._DirectDatabaseCalls["compbio.dundee.ac.uk"]=null;
+     * @j2sNative J2S.db._DirectDatabaseCalls["jalview.org"]=null;
+     * 
+     */
     System.out
             .println("Java version: " + System.getProperty("java.version"));
     System.out.println("Java Home: " + System.getProperty("java.home"));
@@ -308,25 +310,22 @@ public class Jalview implements JalviewJSApi
     Cache.getInstance().loadBuildProperties(true);
 
     ArgsParser aparser = new ArgsParser(args);
-    headless = false;
+    boolean headless = false;
 
     String usrPropsFile = aparser.getValue("props");
-
     Cache.loadProperties(usrPropsFile); // must do this before
-
+    boolean allowServices = true;
+    
     if (isJS)
     {
-      isJavaAppletTag = aparser.isApplet();
-      if (isJavaAppletTag)
-      {
-        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");
+      j2sAppletID = Platform.getAppID(null);
+      Preferences.setAppletDefaults();
+      Cache.loadProperties(usrPropsFile); // again, because we
+      // might be changing defaults here?
+      appletResourcePath = (String) aparser.getAppletValue("resourcepath",
+              null, true);
     }
+
     else
     /**
      * Java only
@@ -334,7 +333,6 @@ public class Jalview implements JalviewJSApi
      * @j2sIgnore
      */
     {
-
       if (usrPropsFile != null)
       {
         System.out.println(
@@ -345,19 +343,23 @@ public class Jalview implements JalviewJSApi
         showUsage();
         System.exit(0);
       }
-      // ?>>
+      // BH note: Only -nodisplay is official; others are deprecated?
       if (aparser.contains("nodisplay") || aparser.contains("nogui")
-              || aparser.contains("headless"))
+              || aparser.contains("headless")
+              || GraphicsEnvironment.isHeadless())
       {
-        System.setProperty("java.awt.headless", "true");
+        if (!isJS) {
+          // BH Definitely not a good idea in JavaScript; 
+          // probably should not be here for Java, either.  
+          System.setProperty("java.awt.headless", "true");
+        }
         headless = true;
       }
-      // <<?
-
       // anything else!
 
       final String jabawsUrl = aparser.getValue(ArgsParser.JABAWS);
-      if (jabawsUrl != null)
+      allowServices = !("none".equals(jabawsUrl));
+      if (allowServices && jabawsUrl != null)
       {
         try
         {
@@ -410,61 +412,13 @@ public class Jalview implements JalviewJSApi
 
     desktop = null;
 
-    if (!isJS)
-    /** @j2sIgnore */
-    {
-      try
-      {
-        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-      } catch (Exception ex)
-      {
-        System.err.println("Unexpected Look and Feel Exception");
-        ex.printStackTrace();
-      }
-      if (Platform.isMac())
-      {
+    setLookAndFeel();
 
-        LookAndFeel lookAndFeel = ch.randelshofer.quaqua.QuaquaManager
-                .getLookAndFeel();
-        System.setProperty(
-                "com.apple.mrj.application.apple.menu.about.name",
-                "Jalview");
-        System.setProperty("apple.laf.useScreenMenuBar", "true");
-        if (lookAndFeel != null)
-        {
-          try
-          {
-            UIManager.setLookAndFeel(lookAndFeel);
-          } catch (Throwable e)
-          {
-            System.err.println(
-                    "Failed to set QuaQua look and feel: " + e.toString());
-          }
-        }
-        if (lookAndFeel == null
-                || !(lookAndFeel.getClass().isAssignableFrom(
-                        UIManager.getLookAndFeel().getClass()))
-                || !UIManager.getLookAndFeel().getClass().toString()
-                        .toLowerCase().contains("quaqua"))
-        {
-          try
-          {
-            System.err.println(
-                    "Quaqua LaF not available on this plaform. Using VAqua(4).\nSee https://issues.jalview.org/browse/JAL-2976");
-            UIManager.setLookAndFeel("org.violetlib.aqua.AquaLookAndFeel");
-          } catch (Throwable e)
-          {
-            System.err.println(
-                    "Failed to reset look and feel: " + e.toString());
-          }
-        }
-      }
-    }
     /*
      * configure 'full' SO model if preferences say to, else use the default (full SO)
      * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
      */
-    boolean soDefault = !Platform.isJS();
+    boolean soDefault = !isJS;
     if (Cache.getDefault("USE_FULL_SO", soDefault))
     {
       SequenceOntologyFactory.setInstance(new SequenceOntology());
@@ -472,27 +426,45 @@ public class Jalview implements JalviewJSApi
 
     if (!headless)
     {
-      desktop = new Desktop();
+      Desktop.nosplash = aparser.contains("nosplash");
+      desktop = Desktop.getInstance();
       desktop.setInBatchMode(true); // indicate we are starting up
 
       try
       {
         JalviewTaskbar.setTaskbar(this);
+      } catch (Exception e)
+      {
+        Cache.log.info("Cannot set Taskbar");
+        Cache.log.error(e.getMessage());
+        // e.printStackTrace();
       } catch (Throwable t)
       {
-        System.out.println("Error setting Taskbar: " + t.getMessage());
+        Cache.log.info("Cannot set Taskbar");
+        Cache.log.error(t.getMessage());
+        // t.printStackTrace();
       }
+      // set Proxy settings before all the internet calls
+      Cache.setProxyPropertiesFromPreferences();
 
       desktop.setVisible(true);
 
-      if (!Platform.isJS())
+      if (isJS)
+      {
+        Cache.setProperty("SHOW_JWS2_SERVICES", "false");
+      }
+      if (allowServices && !aparser.contains("nowebservicediscovery"))
+      {
+        desktop.startServiceDiscovery();
+      }
+
+      if (!isJS)
       /**
        * Java only
        * 
        * @j2sIgnore
        */
       {
-        desktop.startServiceDiscovery();
         if (!aparser.contains("nousagestats"))
         {
           startUsageStats(desktop);
@@ -523,7 +495,7 @@ public class Jalview implements JalviewJSApi
               // String defurl =
               // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
               // //
-              String defurl = "http://www.jalview.org/cgi-bin/questionnaire.pl";
+              String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
               Cache.log.debug(
                       "Starting questionnaire with default url: " + defurl);
               desktop.checkForQuestionnaire(defurl);
@@ -544,37 +516,20 @@ public class Jalview implements JalviewJSApi
         BioJsHTMLOutput.updateBioJS();
       }
     }
-
     parseArguments(aparser, true);
   }
 
   /**
-   * Allow an outside entity to initiate the second half of argument parsing
-   * (only).
+   * Parse all command-line String[] arguments as well as all JavaScript-derived
+   * parameters from Info.
    * 
-   * @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;
-    }
-  }
-
-  /**
+   * We allow for this method to be run from JavaScript. Basically allowing
+   * simple scripting.
    * 
    * @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
@@ -604,23 +559,84 @@ public class Jalview implements JalviewJSApi
       // completed one way or another
       // extract groovy argument and execute if necessary
       groovyscript = aparser.getValue("groovy", true);
-
     }
 
     String file = aparser.getValue("open", true);
 
-    if (file == null && desktop == null)
+    if (!isJS && file == null && desktop == null)
     {
       System.out.println("No files to open!");
       System.exit(1);
     }
-
+    setDisplayParameters(aparser);
+    
+    // time to open a file.
     long progress = -1;
     DataSourceType protocol = null;
     FileLoader fileLoader = new FileLoader(!headless);
     FileFormatI format = null;
     // Finally, deal with the remaining input data.
-    if (file != null)
+    AlignFrame af = null;
+
+    JalviewJSApp jsApp = (isJS ? new JalviewJSApp(this, aparser) : null);
+
+    if (file == null)
+    {
+      if (isJS)
+      {
+        // JalviewJS allows sequence1 sequence2 ....
+        
+      }
+      else if (!headless && Cache.getDefault("SHOW_STARTUP_FILE", true))
+      /**
+       * Java only
+       * 
+       * @j2sIgnore
+       */
+      {
+
+        // We'll only open the default file if the desktop is visible.
+        // And the user
+        // ////////////////////
+
+        file = Cache.getDefault("STARTUP_FILE",
+                Cache.getDefault("www.jalview.org",
+                        "http://www.jalview.org")
+                        + "/examples/exampleFile_2_7.jar");
+        if (file.equals(
+                "http://www.jalview.org/examples/exampleFile_2_3.jar"))
+        {
+          // hardwire upgrade of the startup file
+          file.replace("_2_3.jar", "_2_7.jar");
+          // and remove the stale setting
+          Cache.removeProperty("STARTUP_FILE");
+        }
+
+        protocol = DataSourceType.FILE;
+
+        if (file.indexOf("http:") > -1)
+        {
+          protocol = DataSourceType.URL;
+        }
+
+        if (file.endsWith(".jar"))
+        {
+          format = FileFormat.Jalview;
+        }
+        else
+        {
+          try
+          {
+            format = new IdentifyFile().identify(file, protocol);
+          } catch (FileFormatException e)
+          {
+            // TODO what?
+          }
+        }
+        af = fileLoader.LoadFileWaitTillLoaded(file, protocol, format);
+      }
+    }
+    else
     {
       if (!headless)
       {
@@ -638,8 +654,7 @@ public class Jalview implements JalviewJSApi
        * @j2sIgnore
        */
       {
-        if (!file.startsWith("http://") && !file.startsWith("https://"))
-        // BH 2019 added https check for Java
+        if (!HttpUtils.startsWithHttpOrHttps(file))
         {
           if (!(new File(file)).exists())
           {
@@ -651,58 +666,36 @@ public class Jalview implements JalviewJSApi
           }
         }
       }
-      String fileFormat = (isJavaAppletTag
-              ? aparser.getAppletValue("format", null)
+
+      // JS Only argument to provide a format parameter to specify what format to use
+      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 ?
       }
 
-      if (aparser.contains(ArgsParser.NOMENUBAR))
-      {
-        noMenuBar = true;
-        System.out.println("CMD [nomenu] executed successfully!");
-      }
-
-      if (aparser.contains(ArgsParser.NOSTATUS))
-      {
-        noStatus = true;
-        System.out.println("CMD [nostatus] executed successfully!");
-      }
-
-      if (aparser.contains(ArgsParser.NOANNOTATION)
-              || aparser.contains(ArgsParser.NOANNOTATION2))
-      {
-        noAnnotation = true;
-        System.out.println("CMD no-annotation executed successfully!");
-      }
-      if (aparser.contains(ArgsParser.NOCALCULATION))
-      {
-        noCalculation = true;
-        System.out.println("CMD [nocalculation] executed successfully!");
-      }
-
-      AlignFrame af = new FileLoader(!headless).LoadFileWaitTillLoaded(file,
-              protocol, format);
+      af = new FileLoader(!headless).LoadFileWaitTillLoaded(file, protocol,
+              format);
       if (af == null)
       {
-        System.out.println("error");
+        System.out.println("jalview error - AlignFrame was not created");
       }
       else
       {
-
+        
         // JalviewLite interface for JavaScript allows second file open
         String file2 = aparser.getValue(ArgsParser.OPEN2, true);
         if (file2 != null)
@@ -731,137 +724,16 @@ public class Jalview implements JalviewJSApi
                     "CMD [-open2 " + file2 + "] executed successfully!");
           }
         }
+        // af is loaded - so set it as current frame
         setCurrentAlignFrame(af);
 
-        String data = aparser.getValue(ArgsParser.COLOUR, true);
-        if (data != null)
-        {
-          data.replaceAll("%20", " ");
-
-          ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
-                  af.getViewport(), af.getViewport().getAlignment(), data);
-
-          if (cs != null)
-          {
-            System.out.println(
-                    "CMD [-color " + data + "] executed successfully!");
-          }
-          af.changeColour(cs);
-        }
-
-        // Must maintain ability to use the groups flag
-        data = aparser.getValue(ArgsParser.GROUPS, true);
-        if (data != null)
-        {
-          af.parseFeaturesFile(data,
-                  AppletFormatAdapter.checkProtocol(data));
-          // System.out.println("Added " + data);
-          System.out.println(
-                  "CMD groups[-" + data + "]  executed successfully!");
-        }
-        data = aparser.getValue(ArgsParser.FEATURES, true);
-        if (data != null)
-        {
-          af.parseFeaturesFile(data,
-                  AppletFormatAdapter.checkProtocol(data));
-          // System.out.println("Added " + data);
-          System.out.println(
-                  "CMD [-features " + data + "]  executed successfully!");
-        }
-        data = aparser.getValue(ArgsParser.ANNOTATIONS, true);
-        if (data != null)
-        {
-          af.loadJalviewDataFile(data, null, null, null);
-          // System.out.println("Added " + data);
-          System.out.println(
-                  "CMD [-annotations " + data + "] executed successfully!");
-        }
-
-        // JavaScript feature
-
-        if (aparser.contains(ArgsParser.SHOWOVERVIEW))
-        {
-          af.overviewMenuItem_actionPerformed(null);
-          System.out.println("CMD [showoverview] executed successfully!");
-        }
-
-        // set or clear the sortbytree flag.
-        if (aparser.contains(ArgsParser.SORTBYTREE))
-        {
-          af.getViewport().setSortByTree(true);
-          if (af.getViewport().getSortByTree())
-          {
-            System.out.println("CMD [-sortbytree] executed successfully!");
-          }
-        }
-
-        boolean doUpdateAnnotation = false;
-        /**
-         * we do this earlier in JalviewJS because of a complication with
-         * SHOWOVERVIEW
-         * 
-         * For now, just fixing this in JalviewJS.
-         *
-         * 
-         * @j2sIgnore
-         * 
-         */
-        {
-          if (aparser.contains(ArgsParser.NOANNOTATION)
-                  || aparser.contains(ArgsParser.NOANNOTATION2))
-          {
-            af.getViewport().setShowAnnotation(false);
-            if (!af.getViewport().isShowAnnotation())
-            {
-              doUpdateAnnotation = true;
-              System.out
-                      .println("CMD no-annotation executed successfully!");
-            }
-          }
-        }
-        
+        setFrameDependentProperties(aparser, af);
         
-        if (aparser.contains(ArgsParser.NOSORTBYTREE))
-        {
-          af.getViewport().setSortByTree(false);
-          if (!af.getViewport().getSortByTree())
-          {
-            doUpdateAnnotation = true;
-            System.out
-                    .println("CMD [-nosortbytree] executed successfully!");
-          }
-        }
-        if (doUpdateAnnotation)
-        { // BH 2019.07.24
-          af.setMenusForViewport();
-          af.alignPanel.updateLayout();
-        }
-
-        data = aparser.getValue(ArgsParser.TREE, true);
-        if (data != null)
-        {
-          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());
-          } catch (IOException ex)
-          {
-            System.err.println("Couldn't add tree " + data);
-            ex.printStackTrace(System.err);
-          }
-        }
-        // 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);
+          jsApp.initFromParams(af);
         }
-        else if (!isJS)
+        else
         /**
          * Java only
          * 
@@ -880,75 +752,27 @@ public class Jalview implements JalviewJSApi
             groovyscript = null;
           }
         }
-        createOutputFiles(aparser, af, format);
-        while (aparser.getSize() > 0)
-        {
-          System.out.println("Unknown arg: " + aparser.nextValue());
+        if (!isJS || !isStartup) {
+          createOutputFiles(aparser, format);
         }
       }
-    }
-    
-    
-    AlignFrame startUpAlframe = null;
-    // We'll only open the default file if the desktop is visible.
-    // And the user
-    // ////////////////////
-
-    if (!isJS && !headless && file == null
-            && Cache.getDefault("SHOW_STARTUP_FILE", true))
-    /**
-     * Java only
-     * 
-     * @j2sIgnore
-     */
-    {
-      file = Cache.getDefault("STARTUP_FILE",
-              Cache.getDefault("www.jalview.org", "http://www.jalview.org")
-                      + "/examples/exampleFile_2_7.jar");
-      if (file.equals(
-              "http://www.jalview.org/examples/exampleFile_2_3.jar"))
-      {
-        // hardwire upgrade of the startup file
-        file.replace("_2_3.jar", "_2_7.jar");
-        // and remove the stale setting
-        Cache.removeProperty("STARTUP_FILE");
-      }
-
-      protocol = DataSourceType.FILE;
-
-      if (file.indexOf("http:") > -1)
-      {
-        protocol = DataSourceType.URL;
-      }
-
-      if (file.endsWith(".jar"))
-      {
-        format = FileFormat.Jalview;
-      }
-      else
+      if (headless)
       {
-        try
-        {
-          format = new IdentifyFile().identify(file, protocol);
-        } catch (FileFormatException e)
-        {
-          // TODO what?
-        }
+        af.getViewport().getCalcManager().shutdown();
       }
-
-      startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
-              format);
-
     }
-    
     // extract groovy arguments before anything else.
     // Once all other stuff is done, execute any groovy scripts (in order)
-    if (groovyscript != null)
+    if (!isJS && groovyscript != null)
     {
       if (Cache.groovyJarsPresent())
       {
+        // TODO: DECIDE IF THIS SECOND PASS AT GROOVY EXECUTION IS STILL REQUIRED !!
         System.out.println("Executing script " + groovyscript);
-        executeGroovyScript(groovyscript, startUpAlframe);
+        executeGroovyScript(groovyscript, af);
+        System.out.println("CMD groovy[" + groovyscript
+                    + "] executed successfully!");
+
       }
       else
       {
@@ -967,67 +791,220 @@ public class Jalview implements JalviewJSApi
       }
       desktop.setInBatchMode(false);
     }
+    
+    if (jsApp != null) {
+      jsApp.callInitCallback();
+    }
   }
-
+  
   /**
-   * Writes an output file for each format (if any) specified in the
-   * command-line arguments. Supported formats are currently
-   * <ul>
-   * <li>png</li>
-   * <li>svg</li>
-   * <li>html</li>
-   * <li>biojsmsa</li>
-   * <li>imgMap</li>
-   * <li>eps</li>
-   * </ul>
-   * A format parameter should be followed by a parameter specifying the output
-   * file name. {@code imgMap} parameters should follow those for the
-   * corresponding alignment image output.
+   * Set general display parameters irrespective of file loading or headlessness.
    * 
    * @param aparser
-   * @param af
-   * @param format
    */
-  private void createOutputFiles(ArgsParser aparser, AlignFrame af,
-          FileFormatI format)
+  private void setDisplayParameters(ArgsParser aparser)
   {
-    String imageName = "unnamed.png";
-    while (aparser.getSize() > 1)
+    if (aparser.contains(ArgsParser.NOMENUBAR))
     {
-      String outputFormat = aparser.nextValue();
-      String file = aparser.nextValue();
+      noMenuBar = true;
+      System.out.println("CMD [nomenu] executed successfully!");
+    }
 
-      if (outputFormat.equalsIgnoreCase("png"))
-      {
-        af.createPNG(new File(file));
-        imageName = (new File(file)).getName();
-        System.out.println("Creating PNG image: " + file);
-        continue;
-      }
-      else if (outputFormat.equalsIgnoreCase("svg"))
-      {
-        File imageFile = new File(file);
-        imageName = imageFile.getName();
-        af.createSVG(imageFile);
-        System.out.println("Creating SVG image: " + file);
-        continue;
+    if (aparser.contains(ArgsParser.NOSTATUS))
+    {
+      noStatus = true;
+      System.out.println("CMD [nostatus] executed successfully!");
+    }
+
+    if (aparser.contains(ArgsParser.NOANNOTATION)
+            || aparser.contains(ArgsParser.NOANNOTATION2))
+    {
+      noAnnotation = true;
+      System.out.println("CMD no-annotation executed successfully!");
+    }
+    if (aparser.contains(ArgsParser.NOCALCULATION))
+    {
+      noCalculation = true;
+      System.out.println("CMD [nocalculation] executed successfully!");
+    }
+  }
+
+
+  private void setFrameDependentProperties(ArgsParser aparser,
+          AlignFrame af)
+  {
+    String data = aparser.getValue(ArgsParser.COLOUR, true);
+    if (data != null)
+    {
+      data.replaceAll("%20", " ");
+
+      ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
+              af.getViewport(), af.getViewport().getAlignment(), data);
+
+      if (cs != null)
+      {
+        System.out.println(
+                "CMD [-color " + data + "] executed successfully!");
       }
-      else if (outputFormat.equalsIgnoreCase("html"))
+      af.changeColour(cs);
+    }
+
+    // Must maintain ability to use the groups flag
+    data = aparser.getValue(ArgsParser.GROUPS, true);
+    if (data != null)
+    {
+      af.parseFeaturesFile(data,
+              AppletFormatAdapter.checkProtocol(data));
+      // System.out.println("Added " + data);
+      System.out.println(
+              "CMD groups[-" + data + "]  executed successfully!");
+    }
+    data = aparser.getValue(ArgsParser.FEATURES, true);
+    if (data != null)
+    {
+      af.parseFeaturesFile(data,
+              AppletFormatAdapter.checkProtocol(data));
+      // System.out.println("Added " + data);
+      System.out.println(
+              "CMD [-features " + data + "]  executed successfully!");
+    }
+    data = aparser.getValue(ArgsParser.ANNOTATIONS, true);
+    if (data != null)
+    {
+      af.loadJalviewDataFile(data, null, null, null);
+      // System.out.println("Added " + data);
+      System.out.println(
+              "CMD [-annotations " + data + "] executed successfully!");
+    }
+
+    // JavaScript feature
+
+    if (aparser.contains(ArgsParser.SHOWOVERVIEW))
+    {
+      af.overviewMenuItem_actionPerformed(null);
+      System.out.println("CMD [showoverview] executed successfully!");
+    }
+
+    // set or clear the sortbytree flag.
+    if (aparser.contains(ArgsParser.SORTBYTREE))
+    {
+      af.getViewport().setSortByTree(true);
+      if (af.getViewport().getSortByTree())
       {
-        File imageFile = new File(file);
-        imageName = imageFile.getName();
-        HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
-        htmlSVG.exportHTML(file);
-        System.out.println("Creating HTML image: " + file);
-        continue;
+        System.out.println("CMD [-sortbytree] executed successfully!");
       }
-      else if (outputFormat.equalsIgnoreCase("biojsmsa"))
+    }
+
+    boolean doUpdateAnnotation = false;
+    /**
+     * we do this earlier in JalviewJS because of a complication with
+     * SHOWOVERVIEW
+     * 
+     * For now, just fixing this in JalviewJS.
+     *
+     * 
+     * @j2sIgnore
+     * 
+     */
+    {
+      if (noAnnotation)
       {
-        if (file == null)
+        af.getViewport().setShowAnnotation(false);
+        if (!af.getViewport().isShowAnnotation())
         {
-          System.err.println("The output html file must not be null");
-          return;
+          doUpdateAnnotation = true;
         }
+      }
+    }
+
+    if (aparser.contains(ArgsParser.NOSORTBYTREE))
+    {
+      af.getViewport().setSortByTree(false);
+      if (!af.getViewport().getSortByTree())
+      {
+        doUpdateAnnotation = true;
+        System.out
+                .println("CMD [-nosortbytree] executed successfully!");
+      }
+    }
+    if (doUpdateAnnotation)
+    { // BH 2019.07.24
+      af.setMenusForViewport();
+      af.alignPanel.updateLayout();
+    }
+
+    data = aparser.getValue(ArgsParser.TREE, true);
+    if (data != null)
+    {
+      try
+      {
+        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);
+        ex.printStackTrace(System.err);
+      }
+    }
+    // TODO - load PDB structure(s) to alignment JAL-629
+    // (associate with identical sequence in alignment, or a specified
+    // sequence)
+
+  }
+
+  /**
+   * Writes an output file for each format (if any) specified in the
+   * command-line arguments. Supported formats are currently
+   * <ul>
+   * <li>png</li>
+   * <li>svg</li>
+   * <li>html</li>
+   * <li>biojsmsa</li>
+   * <li>imgMap</li>
+   * <li>eps</li>
+   * </ul>
+   * A format parameter should be followed by a parameter specifying the output
+   * file name. {@code imgMap} parameters should follow those for the
+   * corresponding alignment image output.
+   * 
+   * @param aparser
+   * @param format
+   */
+  private void createOutputFiles(ArgsParser aparser, FileFormatI format)
+  {
+    // logic essentially the same as 2.11.2/2.11.3 but uses a switch instead
+    AlignFrame af = currentAlignFrame;
+    while (aparser.getSize() >= 2)
+    {
+      String outputFormat = aparser.nextValue();
+      File imageFile;
+      String fname;
+      switch (outputFormat.toLowerCase(Locale.ROOT))
+      {
+      case "png":
+        imageFile = new File(aparser.nextValue());
+        af.createPNG(imageFile);
+        System.out.println(
+                "Creating PNG image: " + imageFile.getAbsolutePath());
+        continue;
+      case "svg":
+        imageFile = new File(aparser.nextValue());
+        af.createSVG(imageFile);
+        System.out.println(
+                "Creating SVG image: " + imageFile.getAbsolutePath());
+        continue;
+      case "eps":
+        imageFile = new File(aparser.nextValue());
+        System.out.println(
+                "Creating EPS file: " + imageFile.getAbsolutePath());
+        af.createEPS(imageFile);
+        continue;
+      case "biojsmsa":
+        fname = new File(aparser.nextValue()).getAbsolutePath();
         try
         {
           BioJsHTMLOutput.refreshVersionInfo(
@@ -1037,41 +1014,272 @@ public class Jalview implements 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;
+      default:
+        // fall through - try to parse as an alignment data export format
+        FileFormatI outFormat = null;
+        try
+        {
+          outFormat = FileFormats.getInstance().forName(outputFormat);
+        } catch (Exception formatP)
+        {
+        }
+        if (outFormat == null)
+        {
+          System.out.println("Couldn't parse " + outputFormat
+                  + " as a valid Jalview format string.");
+          continue;
+        }
+        if (!outFormat.isWritable())
+        {
+          System.out.println(
+                  "This version of Jalview does not support alignment export as "
+                          + outputFormat);
+          continue;
+        }
+        // record file as it was passed to Jalview so it is recognisable to the CLI
+        // caller
+        String file;
+        fname = new File(file = aparser.nextValue()).getAbsolutePath();
+        // JBPNote - yuck - really wish we did have a bean returned from this which gave
+        // success/fail like before !
+        af.saveAlignment(fname, outFormat);
+        if (!af.isSaveAlignmentSuccessful())
+        {
+          System.out.println("Written alignment in " + outputFormat
+                  + " format to " + file);
+          continue;
+        }
+        else
+        {
+          System.out.println("Error writing file " + file + " in "
+                  + outputFormat + " format!!");
+        }
       }
+    }
+    // ??? Should report - 'ignoring' extra args here...
+    while (aparser.getSize() > 0)
+    {
+      System.out.println("Ignoring extra argument: " + aparser.nextValue());
+    }
+  }
 
-      af.saveAlignment(file, format);
-      if (af.isSaveAlignmentSuccessful())
+  private static void setLookAndFeel()
+  {
+    // property laf = "crossplatform", "system", "gtk", "metal", "nimbus" or
+    // "mac"
+    // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
+    // try Quaqua/Vaqua.
+    String lafProp = System.getProperty("laf");
+    String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
+    String laf = "none";
+    if (lafProp != null)
+    {
+      laf = lafProp;
+    }
+    else if (lafSetting != null)
+    {
+      laf = lafSetting;
+    }
+    boolean lafSet = false;
+    switch (laf)
+    {
+    case "crossplatform":
+      lafSet = setCrossPlatformLookAndFeel();
+      if (!lafSet)
       {
-        System.out.println(
-                "Written alignment in " + format + " format to " + file);
+        Cache.log.error("Could not set requested laf=" + laf);
       }
-      else
+      break;
+    case "system":
+      lafSet = setSystemLookAndFeel();
+      if (!lafSet)
+      {
+        Cache.log.error("Could not set requested laf=" + laf);
+      }
+      break;
+    case "gtk":
+      lafSet = setGtkLookAndFeel();
+      if (!lafSet)
+      {
+        Cache.log.error("Could not set requested laf=" + laf);
+      }
+      break;
+    case "metal":
+      lafSet = setMetalLookAndFeel();
+      if (!lafSet)
+      {
+        Cache.log.error("Could not set requested laf=" + laf);
+      }
+      break;
+    case "nimbus":
+      lafSet = setNimbusLookAndFeel();
+      if (!lafSet)
+      {
+        Cache.log.error("Could not set requested laf=" + laf);
+      }
+      break;
+    case "quaqua":
+      lafSet = setQuaquaLookAndFeel();
+      if (!lafSet)
+      {
+        Cache.log.error("Could not set requested laf=" + laf);
+      }
+      break;
+    case "vaqua":
+      lafSet = setVaquaLookAndFeel();
+      if (!lafSet)
+      {
+        Cache.log.error("Could not set requested laf=" + laf);
+      }
+      break;
+    case "mac":
+      lafSet = setMacLookAndFeel();
+      if (!lafSet)
+      {
+        Cache.log.error("Could not set requested laf=" + laf);
+      }
+      break;
+    case "none":
+      break;
+    default:
+      Cache.log.error("Requested laf=" + laf + " not implemented");
+    }
+    if (!lafSet)
+    {
+      setSystemLookAndFeel();
+      if (Platform.isLinux())
+      {
+        setMetalLookAndFeel();
+      }
+      if (Platform.isMac())
       {
-        System.out.println("Error writing file " + file + " in " + format
-                + " format!!");
+        setMacLookAndFeel();
       }
+    }
+  }
+
+  private static boolean setCrossPlatformLookAndFeel()
+  {
+    boolean set = false;
+    try
+    {
+      UIManager.setLookAndFeel(
+              UIManager.getCrossPlatformLookAndFeelClassName());
+      set = true;
+    } catch (Exception ex)
+    {
+      Cache.log.error("Unexpected Look and Feel Exception");
+      Cache.log.error(ex.getMessage());
+      Cache.log.debug(Cache.getStackTraceString(ex));
+    }
+    return set;
+  }
+
+  private static boolean setSystemLookAndFeel()
+  {
+    boolean set = false;
+    try
+    {
+      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+      set = true;
+    } catch (Exception ex)
+    {
+      Cache.log.error("Unexpected Look and Feel Exception");
+      Cache.log.error(ex.getMessage());
+      Cache.log.debug(Cache.getStackTraceString(ex));
+    }
+    return set;
+  }
 
+  private static boolean setSpecificLookAndFeel(String name,
+          String className, boolean nameStartsWith)
+  {
+    boolean set = false;
+    try
+    {
+      for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
+      {
+        if (info.getName() != null && nameStartsWith
+                ? info.getName().toLowerCase(Locale.ROOT)
+                        .startsWith(name.toLowerCase(Locale.ROOT))
+                : info.getName().toLowerCase(Locale.ROOT).equals(name.toLowerCase(Locale.ROOT)))
+        {
+          className = info.getClassName();
+          break;
+        }
+      }
+      UIManager.setLookAndFeel(className);
+      set = true;
+    } catch (Exception ex)
+    {
+      Cache.log.error("Unexpected Look and Feel Exception");
+      Cache.log.error(ex.getMessage());
+      Cache.log.debug(Cache.getStackTraceString(ex));
     }
+    return set;
+  }
+
+  private static boolean setGtkLookAndFeel()
+  {
+    return setSpecificLookAndFeel("gtk",
+            "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
+  }
+
+  private static boolean setMetalLookAndFeel()
+  {
+    return setSpecificLookAndFeel("metal",
+            "javax.swing.plaf.metal.MetalLookAndFeel", false);
+  }
+
+  private static boolean setNimbusLookAndFeel()
+  {
+    return setSpecificLookAndFeel("nimbus",
+            "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
+  }
+
+  private static boolean setQuaquaLookAndFeel()
+  {
+    return setSpecificLookAndFeel("quaqua",
+            ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
+                    .getName(),
+            false);
+  }
 
+  private static boolean setVaquaLookAndFeel()
+  {
+    return setSpecificLookAndFeel("vaqua",
+            "org.violetlib.aqua.AquaLookAndFeel", false);
   }
 
+  private static boolean setMacLookAndFeel()
+  {
+    boolean set = false;
+    System.setProperty("com.apple.mrj.application.apple.menu.about.name",
+            ChannelProperties.getProperty("app_name"));
+    System.setProperty("apple.laf.useScreenMenuBar", "true");
+    set = setQuaquaLookAndFeel();
+    if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
+            .toLowerCase(Locale.ROOT).contains("quaqua"))
+    {
+      set = setVaquaLookAndFeel();
+    }
+    return set;
+  }
   private static void showUsage()
   {
     System.out.println(
@@ -1110,7 +1318,9 @@ public class Jalview implements JalviewJSApi
                     + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
                     + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
                     + "-groovy FILE\tExecute groovy script in FILE, after all other arguments have been processed (if FILE is the text 'STDIN' then the file will be read from STDIN)\n"
-                    + "\n~Read documentation in Application or visit http://www.jalview.org for description of Features and Annotations file~\n\n");
+                    + "-jvmmempc=PERCENT\tOnly available with standalone executable jar or jalview.bin.Launcher. Limit maximum heap size (memory) to PERCENT% of total physical memory detected. This defaults to 90 if total physical memory can be detected. See https://www.jalview.org/help/html/memory.html for more details.\n"
+                    + "-jvmmemmax=MAXMEMORY\tOnly available with standalone executable jar or jalview.bin.Launcher. Limit maximum heap size (memory) to MAXMEMORY. MAXMEMORY can be specified in bytes, kilobytes(k), megabytes(m), gigabytes(g) or if you're lucky enough, terabytes(t). This defaults to 32g if total physical memory can be detected, or to 8g if total physical memory cannot be detected. See https://www.jalview.org/help/html/memory.html for more details.\n"
+                    + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
   }
 
   private static void startUsageStats(final Desktop desktop)
@@ -1118,7 +1328,7 @@ public class Jalview implements JalviewJSApi
     /**
      * start a User Config prompt asking if we can log usage statistics.
      */
-    PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
+    PromptUserConfig prompter = new PromptUserConfig(Desktop.getDesktopPane(),
             "USAGESTATS", "Jalview Usage Statistics",
             "Do you want to help make Jalview better by enabling "
                     + "the collection of usage statistics with Google Analytics ?"
@@ -1280,8 +1490,8 @@ public class Jalview implements JalviewJSApi
   }
 
   /**
-   * Quit method delegates to Desktop.quit - unless running in headless mode
-   * when it just ends the JVM
+   * Quit method delegates to Desktop.quit - unless running in headless mode when
+   * it just ends the JVM
    */
   public void quit()
   {
@@ -1297,813 +1507,30 @@ public class Jalview implements 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
-   * 
-   * @param frameType
-   *          "alignment", "desktop", etc., or null
-   * @return
-   */
-  public static String getAppID(String frameType)
+  
+  public void notifyWorker(AlignCalcWorkerI worker, String status)
   {
-    String id = Cache.getProperty("Info.j2sAppletID");
-    if (id == null)
-    {
-      id = "jalview";
-    }
-    return id + (frameType == null ? "" : "-" + frameType);
+    // System.out.println("Jalview worker " + worker.getClass().getSimpleName()
+    // + " " + status);
   }
 
-  /**
-   * 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);
-      }
+  private static boolean isInteractive = true;
 
-      @Override
-      public void setFeatureGroupState(String[] groups, boolean state)
-      {
-        af.setFeatureGroupState(groups, state);
-      }
+  public static boolean isInteractive()
+  {
+    return isInteractive;
+  }
 
-      @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());
-  }
-
-  /**
-   * 
-   * @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)
+  public static void setInteractive(boolean tf)
   {
-    return appLoader.loadAlignment(text, AlignFrame.DEFAULT_WIDTH,
-            AlignFrame.DEFAULT_HEIGHT, title);
+    isInteractive = tf;
   }
-
-  @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 void notifyWorker(AlignCalcWorkerI worker, String status)
-  {
-    // System.out.println("Jalview worker " + worker.getClass().getSimpleName()
-    // + " " + status);
-  }
-
 }