Merge branch 'features/r2_11_2_alphafold/JAL-629' into features/JAL-3858_PAEsInProjects
[jalview.git] / src / jalview / bin / Jalview.java
index a988a09..99ae815 100755 (executable)
@@ -40,11 +40,14 @@ import java.security.Policy;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Properties;
 import java.util.Vector;
 import java.util.logging.ConsoleHandler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.swing.JDialog;
+import javax.swing.JFrame;
 import javax.swing.JOptionPane;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
@@ -52,6 +55,7 @@ import javax.swing.UIManager.LookAndFeelInfo;
 import javax.swing.UnsupportedLookAndFeelException;
 
 import com.formdev.flatlaf.FlatLightLaf;
+import com.formdev.flatlaf.themes.FlatMacLightLaf;
 import com.formdev.flatlaf.util.SystemInfo;
 import com.threerings.getdown.util.LaunchUtil;
 
@@ -275,30 +279,11 @@ public class Jalview
     if (!Platform.isJS())
     {
       System.setSecurityManager(null);
-
-      Runtime.getRuntime().addShutdownHook(new Thread()
-      {
-        public void run()
-        {
-          Console.debug("Running shutdown hook");
-          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.
-            Console.debug("Checking for saving files");
-            QuitHandler.getQuitResponse(false);
-          }
-          else
-          {
-            Console.debug("Nothing more to do");
-          }
-          Console.debug("Exiting, bye!");
-          // shutdownHook cannot be cancelled, JVM will now halt
-        }
-      });
     }
 
+    // get args needed before proper ArgParser
+    Map<String, String> bootstrapArgs = ArgParser.bootstrapArgs(args);
+
     System.out
             .println("Java version: " + System.getProperty("java.version"));
     System.out.println("Java Home: " + System.getProperty("java.home"));
@@ -322,6 +307,15 @@ public class Jalview
       System.out.println("Launcher version: " + val);
     }
 
+    if (Platform.isLinux() && LaunchUtils.getJavaVersion() < 11)
+    {
+      System.setProperty("flatlaf.uiScale", "1");
+    }
+
+    // get bootstrap properties (mainly for the logger level)
+    Properties bootstrapProperties = Cache
+            .bootstrapProperties(bootstrapArgs.get("props"));
+
     // report Jalview version
     Cache.loadBuildProperties(true);
 
@@ -332,7 +326,12 @@ public class Jalview
 
     try
     {
-      Console.initLogger();
+      String logLevel = bootstrapArgs.containsKey("debug") ? "DEBUG" : null;
+      if (logLevel == null && !(bootstrapProperties == null))
+      {
+        logLevel = bootstrapProperties.getProperty(Cache.JALVIEWLOGLEVEL);
+      }
+      Console.initLogger(logLevel);
     } catch (NoClassDefFoundError error)
     {
       error.printStackTrace();
@@ -341,23 +340,41 @@ public class Jalview
       System.exit(0);
     }
 
-    String usrPropsFile = aparser.getValue("props");
-    Cache.loadProperties(usrPropsFile); // must do this
-                                        // before
+    // register SIGTERM listener
+    Runtime.getRuntime().addShutdownHook(new Thread()
+    {
+      public void run()
+      {
+        Console.debug("Running shutdown hook");
+        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.
+          Console.debug("Checking for saving files");
+          QuitHandler.getQuitResponse(false);
+        }
+        else
+        {
+          Console.debug("Nothing more to do");
+        }
+        Console.debug("Exiting, bye!");
+        // shutdownHook cannot be cancelled, JVM will now halt
+      }
+    });
+
+    String usrPropsFile = bootstrapArgs.containsKey("props")
+            ? bootstrapArgs.get("props")
+            : aparser.getValue("props");
+    Cache.loadProperties(usrPropsFile);
     if (usrPropsFile != null)
     {
       System.out.println(
               "CMD [-props " + usrPropsFile + "] executed successfully!");
     }
 
-    // set log level from cache properties
-    Console.setLogLevel(Cache.getDefault(Cache.JALVIEWLOGLEVEL, "INFO"));
-
     // new ArgParser
-    ArgParser argparser = new ArgParser(args); // do this after
-                                               // Console.initLogger, but TODO
-                                               // want --props before then
-                                               // CATCH22
+    ArgParser argparser = new ArgParser(args);
 
     if (argparser.isSet(Arg.HEADLESS))
       headless = argparser.getBool(Arg.HEADLESS);
@@ -448,6 +465,18 @@ public class Jalview
     System.setProperty("http.agent",
             "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
 
+    try
+    {
+      Console.initLogger();
+    } catch (
+
+    NoClassDefFoundError error)
+    {
+      error.printStackTrace();
+      System.out.println("\nEssential logging libraries not found."
+              + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
+      System.exit(0);
+    }
     desktop = null;
 
     setLookAndFeel();
@@ -941,6 +970,10 @@ public class Jalview
 
       startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
               format);
+      // don't ask to save when quitting if only the startup file has been
+      // opened
+      Console.debug("Resetting up-to-date flag for startup file");
+      startUpAlframe.getViewport().setSavedUpToDate(true);
       // extract groovy arguments before anything else.
     }
 
@@ -1032,20 +1065,6 @@ public class Jalview
         Console.error("Could not set requested laf=" + laf);
       }
       break;
-    case "quaqua":
-      lafSet = setQuaquaLookAndFeel();
-      if (!lafSet)
-      {
-        Console.error("Could not set requested laf=" + laf);
-      }
-      break;
-    case "vaqua":
-      lafSet = setVaquaLookAndFeel();
-      if (!lafSet)
-      {
-        Console.error("Could not set requested laf=" + laf);
-      }
-      break;
     case "mac":
       lafSet = setMacLookAndFeel();
       if (!lafSet)
@@ -1155,54 +1174,103 @@ public class Jalview
   private static boolean setFlatLookAndFeel()
   {
     boolean set = false;
-    if (Platform.isMac()) {
+    if (SystemInfo.isMacOS)
+    {
       try
       {
-        UIManager.setLookAndFeel("com.formdev.flatlaf.themes.FlatMacLightLaf");
+        UIManager.setLookAndFeel(
+                "com.formdev.flatlaf.themes.FlatMacLightLaf");
         set = true;
+        Console.debug("Using FlatMacLightLaf");
       } catch (ClassNotFoundException | InstantiationException
               | IllegalAccessException | UnsupportedLookAndFeelException e)
       {
-        Console.debug("Exception loading FlatMacLightLaf", e);
+        Console.debug("Exception loading FlatLightLaf", e);
+      }
+      System.setProperty("apple.laf.useScreenMenuBar", "true");
+      System.setProperty("apple.awt.application.name",
+              ChannelProperties.getProperty("app_name"));
+      System.setProperty("apple.awt.application.appearance", "system");
+      if (SystemInfo.isMacFullWindowContentSupported
+              && Desktop.desktop != null)
+      {
+        Console.debug("Setting transparent title bar");
+        Desktop.desktop.getRootPane()
+                .putClientProperty("apple.awt.fullWindowContent", true);
+        Desktop.desktop.getRootPane()
+                .putClientProperty("apple.awt.transparentTitleBar", true);
+        Desktop.desktop.getRootPane()
+                .putClientProperty("apple.awt.fullscreenable", true);
       }
+      SwingUtilities.invokeLater(() -> {
+        FlatMacLightLaf.setup();
+      });
+      Console.debug("Using FlatMacLightLaf");
+      set = true;
     }
-    if (!set) {
+    if (!set)
+    {
       try
       {
         UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
         set = true;
+        Console.debug("Using FlatLightLaf");
       } catch (ClassNotFoundException | InstantiationException
               | IllegalAccessException | UnsupportedLookAndFeelException e)
       {
         Console.debug("Exception loading FlatLightLaf", e);
       }
+      // Windows specific properties here
+      SwingUtilities.invokeLater(() -> {
+        FlatLightLaf.setup();
+      });
+      Console.debug("Using FlatLightLaf");
+      set = true;
     }
-    if (set)
+    else if (SystemInfo.isLinux)
     {
-      if (Platform.isMac())
+      try
       {
-        System.setProperty("apple.laf.useScreenMenuBar", "true");
-        System.setProperty("apple.awt.application.name",
-                ChannelProperties.getProperty("app_name"));
-        System.setProperty("apple.awt.application.appearance", "system");
-        if (SystemInfo.isMacFullWindowContentSupported
-                && Desktop.desktop != null)
-        {
-          Desktop.desktop.getRootPane()
-                  .putClientProperty("apple.awt.fullWindowContent", true);
-          Desktop.desktop.getRootPane()
-                  .putClientProperty("apple.awt.transparentTitleBar", true);
-        }
+        UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
+        set = true;
+        Console.debug("Using FlatLightLaf");
+      } catch (ClassNotFoundException | InstantiationException
+              | IllegalAccessException | UnsupportedLookAndFeelException e)
+      {
+        Console.debug("Exception loading FlatLightLaf", e);
+      }
+      // enable custom window decorations
+      JFrame.setDefaultLookAndFeelDecorated(true);
+      JDialog.setDefaultLookAndFeelDecorated(true);
+      SwingUtilities.invokeLater(() -> {
+        FlatLightLaf.setup();
+      });
+      Console.debug("Using FlatLightLaf");
+      set = true;
+    }
 
-        SwingUtilities.invokeLater(() -> {
-          FlatLightLaf.setup();
-        });
+    if (!set)
+    {
+      try
+      {
+        UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
+        set = true;
+        Console.debug("Using FlatLightLaf");
+      } catch (ClassNotFoundException | InstantiationException
+              | IllegalAccessException | UnsupportedLookAndFeelException e)
+      {
+        Console.debug("Exception loading FlatLightLaf", e);
       }
+    }
 
+    if (set)
+    {
+      UIManager.put("TabbedPane.tabType", "card");
       UIManager.put("TabbedPane.showTabSeparators", true);
+      UIManager.put("TabbedPane.showContentSeparator", true);
       UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
       UIManager.put("TabbedPane.tabsOverlapBorder", true);
-      // UIManager.put("TabbedPane.hasFullBorder", true);
+      UIManager.put("TabbedPane.hasFullBorder", true);
       UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
       UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
       UIManager.put("TabbedPane.smoothScrolling", true);
@@ -1214,20 +1282,6 @@ public class Jalview
     return set;
   }
 
-  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;