JAL-4125 Fixed non-closing external viewers, also added options for default behaviour...
[jalview.git] / src / jalview / bin / Jalview.java
index 895268d..8fa4ac7 100755 (executable)
@@ -49,9 +49,11 @@ import java.util.Vector;
 import java.util.logging.ConsoleHandler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.stream.Collectors;
 
 import javax.swing.JDialog;
 import javax.swing.JFrame;
+import javax.swing.JInternalFrame;
 import javax.swing.JOptionPane;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
@@ -68,6 +70,7 @@ import groovy.lang.Binding;
 import groovy.util.GroovyScriptEngine;
 import jalview.bin.argparser.Arg;
 import jalview.bin.argparser.Arg.Opt;
+import jalview.bin.argparser.Arg.Type;
 import jalview.bin.argparser.ArgParser;
 import jalview.bin.argparser.BootstrapArgs;
 import jalview.ext.so.SequenceOntology;
@@ -76,6 +79,7 @@ import jalview.gui.Desktop;
 import jalview.gui.PromptUserConfig;
 import jalview.gui.QuitHandler;
 import jalview.gui.QuitHandler.QResponse;
+import jalview.gui.StructureViewerBase;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.BioJsHTMLOutput;
 import jalview.io.DataSourceType;
@@ -134,6 +138,17 @@ public class Jalview
 
   public static AlignFrame currentAlignFrame;
 
+  public ArgParser argparser = null;
+
+  public BootstrapArgs bootstrapArgs = null;
+
+  private boolean QUIET = false;
+
+  public static boolean quiet()
+  {
+    return Jalview.getInstance() != null && Jalview.getInstance().QUIET;
+  }
+
   static
   {
     if (!Platform.isJS())
@@ -289,36 +304,21 @@ public class Jalview
       System.setSecurityManager(null);
     }
 
-    if (args == null)
-      args = new String[] {};
-
-    // Move any new getdown-launcher-new.jar into place over old
-    // getdown-launcher.jar
-    String appdirString = System.getProperty("getdownappdir");
-    if (appdirString != null && appdirString.length() > 0)
+    if (args == null || args.length == 0 || (args.length == 1
+            && (args[0] == null || args[0].length() == 0)))
     {
-      final File appdir = new File(appdirString);
-      new Thread()
-      {
-        @Override
-        public void run()
-        {
-          LaunchUtil.upgradeGetdown(
-                  new File(appdir, "getdown-launcher-old.jar"),
-                  new File(appdir, "getdown-launcher.jar"),
-                  new File(appdir, "getdown-launcher-new.jar"));
-        }
-      }.start();
+      args = new String[] {};
     }
 
     // get args needed before proper ArgParser
-    BootstrapArgs bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
+    bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
 
     if (!Platform.isJS())
     {
       // are we being --quiet ?
       if (bootstrapArgs.contains(Arg.QUIET))
       {
+        QUIET = true;
         OutputStream devNull = new OutputStream()
         {
 
@@ -335,29 +335,58 @@ public class Jalview
           System.setErr(new PrintStream(devNull));
         }
       }
-    }
-
-    System.out
-            .println("Java version: " + System.getProperty("java.version"));
-    System.out.println("Java Home: " + System.getProperty("java.home"));
-    System.out.println(System.getProperty("os.arch") + " "
-            + System.getProperty("os.name") + " "
-            + System.getProperty("os.version"));
 
-    String val = System.getProperty("sys.install4jVersion");
-    if (val != null)
-    {
-      System.out.println("Install4j version: " + val);
+      if (bootstrapArgs.contains(Arg.HELP)
+              || bootstrapArgs.contains(Arg.VERSION))
+      {
+        QUIET = true;
+      }
     }
-    val = System.getProperty("installer_template_version");
-    if (val != null)
+
+    // Move any new getdown-launcher-new.jar into place over old
+    // getdown-launcher.jar
+    String appdirString = System.getProperty("getdownappdir");
+    if (appdirString != null && appdirString.length() > 0)
     {
-      System.out.println("Install4j template version: " + val);
+      final File appdir = new File(appdirString);
+      new Thread()
+      {
+
+        @Override
+        public void run()
+        {
+          LaunchUtil.upgradeGetdown(
+                  new File(appdir, "getdown-launcher-old.jar"),
+                  new File(appdir, "getdown-launcher.jar"),
+                  new File(appdir, "getdown-launcher-new.jar"));
+        }
+      }.start();
     }
-    val = System.getProperty("launcher_version");
-    if (val != null)
+
+    if (!quiet() || bootstrapArgs.contains(Arg.VERSION))
     {
-      System.out.println("Launcher version: " + val);
+      System.out.println(
+              "Java version: " + System.getProperty("java.version"));
+      System.out.println("Java home: " + System.getProperty("java.home"));
+      System.out.println("Java arch: " + System.getProperty("os.arch") + " "
+              + System.getProperty("os.name") + " "
+              + System.getProperty("os.version"));
+
+      String val = System.getProperty("sys.install4jVersion");
+      if (val != null)
+      {
+        System.out.println("Install4j version: " + val);
+      }
+      val = System.getProperty("installer_template_version");
+      if (val != null)
+      {
+        System.out.println("Install4j template version: " + val);
+      }
+      val = System.getProperty("launcher_version");
+      if (val != null)
+      {
+        System.out.println("Launcher version: " + val);
+      }
     }
 
     if (Platform.isLinux() && LaunchUtils.getJavaVersion() < 11)
@@ -370,7 +399,14 @@ public class Jalview
             .bootstrapProperties(bootstrapArgs.get(Arg.PROPS));
 
     // report Jalview version
-    Cache.loadBuildProperties(true);
+    Cache.loadBuildProperties(
+            !quiet() || bootstrapArgs.contains(Arg.VERSION));
+
+    // stop now if only after --version
+    if (bootstrapArgs.contains(Arg.VERSION))
+    {
+      Jalview.exit(null, 0);
+    }
 
     // old ArgsParser
     ArgsParser aparser = new ArgsParser(args);
@@ -410,11 +446,26 @@ public class Jalview
       public void run()
       {
         Console.debug("Running shutdown hook");
+        QuitHandler.startForceQuit();
+        boolean closeExternal = Cache
+                .getDefault("DEFAULT_CLOSE_EXTERNAL_VIEWERS", false)
+                || Cache.getDefault("ALWAYS_CLOSE_EXTERNAL_VIEWERS", false);
+        StructureViewerBase.setQuitClose(closeExternal);
+        for (JInternalFrame frame : Desktop.desktop.getAllFrames())
+        {
+          if (frame instanceof StructureViewerBase)
+          {
+            ((StructureViewerBase) frame).closeViewer(closeExternal);
+          }
+        }
+
         if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
         {
           // Got to here by a SIGTERM signal.
           // Note we will not actually cancel the quit from here -- it's too
-          // late -- but we can wait for saving files.
+          // late -- but we can wait for saving files and close external viewers
+          // if configured.
+          // Close viewers/Leave viewers open
           Console.debug("Checking for saving files");
           QuitHandler.getQuitResponse(false);
         }
@@ -441,13 +492,11 @@ public class Jalview
               "test/jalview/bin/testProps.jvprops", usrPropsFile);
     }
 
-    // new ArgParser
-    ArgParser argparser;
     // --argfile=... -- OVERRIDES ALL NON-BOOTSTRAP ARGS
     if (bootstrapArgs.contains(Arg.ARGFILE))
     {
       argparser = ArgParser.parseArgFiles(
-              bootstrapArgs.getList(Arg.ARGFILE),
+              bootstrapArgs.getValueList(Arg.ARGFILE),
               bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
               bootstrapArgs);
     }
@@ -467,12 +516,19 @@ public class Jalview
     {
       if (bootstrapArgs.contains(Arg.HELP))
       {
-        System.out.println(Arg.usage());
+        List<Map.Entry<Type, String>> helpArgs = bootstrapArgs
+                .getList(Arg.HELP);
+        System.out.println(Arg.usage(helpArgs.stream().map(e -> e.getKey())
+                .collect(Collectors.toList())));
         Jalview.exit(null, 0);
       }
       if (aparser.contains("help") || aparser.contains("h"))
       {
+        /*
+         * Now using new usage statement.
         showUsage();
+        */
+        System.out.println(Arg.usage());
         Jalview.exit(null, 0);
       }
 
@@ -517,7 +573,7 @@ public class Jalview
     List<String> setprops = new ArrayList<>();
     if (bootstrapArgs.contains(Arg.SETPROP))
     {
-      setprops = bootstrapArgs.getList(Arg.SETPROP);
+      setprops = bootstrapArgs.getValueList(Arg.SETPROP);
     }
     else
     {
@@ -735,7 +791,17 @@ public class Jalview
     {
       if (headlessArg)
       {
-        Jalview.exit("Successfully completed commands in headless mode", 0);
+        if (argparser.getBoolean(Arg.NOQUIT))
+        {
+          Console.warn(
+                  "Completed " + Arg.HEADLESS.getName() + " commands, but "
+                          + Arg.NOQUIT + " is set so not quitting!");
+        }
+        else
+        {
+          Jalview.exit("Successfully completed commands in headless mode",
+                  0);
+        }
       }
       Console.info("Successfully completed commands");
     }
@@ -1197,7 +1263,12 @@ public class Jalview
     }
     if (!lafSet)
     {
-      setSystemLookAndFeel();
+      // Flatlaf default for everyone!
+      lafSet = setFlatLookAndFeel();
+      if (!lafSet)
+      {
+        setSystemLookAndFeel();
+      }
       if (Platform.isLinux())
       {
         setLinuxLookAndFeel();
@@ -1394,6 +1465,8 @@ public class Jalview
       UIManager.put("TabbedPane.smoothScrolling", true);
       UIManager.put("TabbedPane.tabWidthMode", "compact");
       UIManager.put("TabbedPane.selectedBackground", Color.white);
+      UIManager.put("TabbedPane.background", new Color(236, 236, 236));
+      UIManager.put("TabbedPane.hoverColor", Color.lightGray);
     }
 
     Desktop.setLiveDragMode(Cache.getDefault("FLAT_LIVE_DRAG_MODE", true));
@@ -1431,6 +1504,7 @@ public class Jalview
     return set;
   }
 
+  /*
   private static void showUsage()
   {
     System.out.println(
@@ -1473,6 +1547,7 @@ public class Jalview
                     + "-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)
   {
@@ -1666,14 +1741,40 @@ public class Jalview
 
   public static void exit(String message, int exitcode)
   {
-    Console.debug("Using Jalview.exit");
-    if (message != null)
-      if (exitcode == 0)
-        Console.info(message);
-      else
-        Console.error(message);
+    if (Console.log == null)
+    {
+      // Don't start the logger just to exit!
+      if (message != null)
+      {
+        if (exitcode == 0)
+        {
+          System.out.println(message);
+        }
+        else
+        {
+          System.err.println(message);
+        }
+      }
+    }
+    else
+    {
+      Console.debug("Using Jalview.exit");
+      if (message != null)
+      {
+        if (exitcode == 0)
+        {
+          Console.info(message);
+        }
+        else
+        {
+          Console.error(message);
+        }
+      }
+    }
     if (exitcode > -1)
+    {
       System.exit(exitcode);
+    }
   }
 
   /*