Merge branch 'develop' into update_212_Dec_merge_with_21125_chamges
[jalview.git] / src / jalview / bin / Jalview.java
index eca8147..7a8c786 100755 (executable)
  */
 package jalview.bin;
 
+import java.util.Locale;
+
 import java.awt.GraphicsEnvironment;
+import java.awt.Color;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -46,11 +49,16 @@ import java.util.logging.ConsoleHandler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
 import javax.swing.UIManager.LookAndFeelInfo;
 
+import com.formdev.flatlaf.FlatLightLaf;
+import com.formdev.flatlaf.util.SystemInfo;
 import com.threerings.getdown.util.LaunchUtil;
 
+//import edu.stanford.ejalbert.launching.IBrowserLaunching;
 import groovy.lang.Binding;
 import groovy.util.GroovyScriptEngine;
 import jalview.api.AlignCalcWorkerI;
@@ -77,6 +85,7 @@ import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
 import jalview.util.ChannelProperties;
 import jalview.util.HttpUtils;
+import jalview.util.LaunchUtils;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.ws.jws2.Jws2Discoverer;
@@ -123,9 +132,15 @@ public class Jalview implements ApplicationSingletonI
   private Jalview()
   {
     Platform.getURLCommandArguments();
+    Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
+    Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
+    Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
+    Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
   }
 
 
+  private boolean headless;
+
   private Desktop desktop;
 
   public AlignFrame currentAlignFrame;
@@ -160,7 +175,10 @@ public class Jalview implements ApplicationSingletonI
 
   static
   {
-    if (!Platform.isJS())
+    if (Platform.isJS())
+    {
+       Platform.getURLCommandArguments();
+    } else
     /**
      * Java only
      * 
@@ -310,7 +328,7 @@ public class Jalview implements ApplicationSingletonI
     Cache.getInstance().loadBuildProperties(true);
 
     ArgsParser aparser = new ArgsParser(args);
-    boolean headless = false;
+    headless = false;
 
     String usrPropsFile = aparser.getValue("props");
     Cache.loadProperties(usrPropsFile); // must do this before
@@ -357,6 +375,8 @@ public class Jalview implements ApplicationSingletonI
       }
       // anything else!
 
+      // allow https handshakes to download intermediate certs if necessary
+      System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
       final String jabawsUrl = aparser.getValue(ArgsParser.JABAWS);
       allowServices = !("none".equals(jabawsUrl));
       if (allowServices && jabawsUrl != null)
@@ -372,8 +392,8 @@ public class Jalview implements ApplicationSingletonI
                   "Invalid jabaws parameter: " + jabawsUrl + " ignored");
         }
       }
-
     }
+
     String defs = aparser.getValue(ArgsParser.SETPROP);
     while (defs != null)
     {
@@ -401,7 +421,7 @@ public class Jalview implements ApplicationSingletonI
             "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
     try
     {
-      Cache.initLogger();
+      Console.initLogger();
     } catch (NoClassDefFoundError error)
     {
       error.printStackTrace();
@@ -421,7 +441,7 @@ public class Jalview implements ApplicationSingletonI
     boolean soDefault = !isJS;
     if (Cache.getDefault("USE_FULL_SO", soDefault))
     {
-      SequenceOntologyFactory.setInstance(new SequenceOntology());
+      SequenceOntologyFactory.setSequenceOntology(new SequenceOntology());
     }
 
     if (!headless)
@@ -435,15 +455,16 @@ public class Jalview implements ApplicationSingletonI
         JalviewTaskbar.setTaskbar(this);
       } catch (Exception e)
       {
-        Cache.log.info("Cannot set Taskbar");
-        Cache.log.error(e.getMessage());
+        Console.info("Cannot set Taskbar");
+        Console.error(e.getMessage());
         // e.printStackTrace();
       } catch (Throwable t)
       {
-        Cache.log.info("Cannot set Taskbar");
-        Cache.log.error(t.getMessage());
+        Console.info("Cannot set Taskbar");
+        Console.error(t.getMessage());
         // t.printStackTrace();
       }
+
       // set Proxy settings before all the internet calls
       Cache.setProxyPropertiesFromPreferences();
 
@@ -465,6 +486,33 @@ public class Jalview implements ApplicationSingletonI
        * @j2sIgnore
        */
       {
+        /**
+         * Check to see that the JVM version being run is suitable for the Java
+         * version this Jalview was compiled for. Popup a warning if not.
+         */
+        if (!LaunchUtils.checkJavaVersion())
+        {
+          Console.warn("The Java version being used (Java "
+                  + LaunchUtils.getJavaVersion()
+                  + ") may lead to problems. This installation of Jalview should be used with Java "
+                  + LaunchUtils.getJavaCompileVersion() + ".");
+
+          if (!LaunchUtils
+                  .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
+          {
+            Object[] options = {
+                MessageManager.getString("label.continue") };
+            JOptionPane.showOptionDialog(null,
+                    MessageManager.formatMessage(
+                            "warning.wrong_jvm_version_message",
+                            LaunchUtils.getJavaVersion(),
+                            LaunchUtils.getJavaCompileVersion()),
+                    MessageManager
+                            .getString("warning.wrong_jvm_version_title"),
+                    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
+                    null, options, options[0]);
+          }
+        }
         if (!aparser.contains("nousagestats"))
         {
           startUsageStats(desktop);
@@ -481,7 +529,7 @@ public class Jalview implements ApplicationSingletonI
           {
             // Start the desktop questionnaire prompter with the specified
             // questionnaire
-            Cache.log.debug("Starting questionnaire url at " + url);
+            Console.debug("Starting questionnaire url at " + url);
             desktop.checkForQuestionnaire(url);
             System.out.println("CMD questionnaire[-" + url
                     + "] executed successfully!");
@@ -496,7 +544,7 @@ public class Jalview implements ApplicationSingletonI
               // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
               // //
               String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
-              Cache.log.debug(
+              Console.debug(
                       "Starting questionnaire with default url: " + defurl);
               desktop.checkForQuestionnaire(defurl);
             }
@@ -508,14 +556,29 @@ public class Jalview implements ApplicationSingletonI
                   .println("CMD [-noquestionnaire] executed successfully!");
         }
 
-        if (!aparser.contains("nonews"))
+        if (!aparser.contains("nonews")
+                || Cache.getProperty("NONEWS") == null)
         {
           desktop.checkForNews();
         }
 
-        BioJsHTMLOutput.updateBioJS();
+        if (!aparser.contains("nohtmltemplates")
+                || Cache.getProperty("NOHTMLTEMPLATES") == null)
+        {
+          BioJsHTMLOutput.updateBioJS();
+        }
       }
     }
+
+    // Check if JVM and compile version might cause problems and log if it
+    // might.
+    if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
+    {
+      Console.warn("The Java version being used (Java "
+              + LaunchUtils.getJavaVersion()
+              + ") may lead to problems. This installation of Jalview should be used with Java "
+              + LaunchUtils.getJavaCompileVersion() + ".");
+    }
     parseArguments(aparser, true);
   }
 
@@ -588,53 +651,46 @@ public class Jalview implements ApplicationSingletonI
         
       }
       else if (!headless && Cache.getDefault("SHOW_STARTUP_FILE", true))
-      /**
-       * Java only
-       * 
-       * @j2sIgnore
-       */
+    /**
+     * Java only
+     * 
+     * @j2sIgnore
+     */
+    {
+      file = Cache.getDefault("STARTUP_FILE",
+              Cache.getDefault("www.jalview.org", "https://www.jalview.org")
+                      + "/examples/exampleFile_2_7.jvp");
+      if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
+              || file.equals(
+                      "http://www.jalview.org/examples/exampleFile_2_7.jar"))
       {
+        file.replace("http:", "https:");
+        // hardwire upgrade of the startup file
+        file.replace("_2_3", "_2_7");
+        file.replace("2_7.jar", "2_7.jvp");
+        // and remove the stale setting
+        Cache.removeProperty("STARTUP_FILE");
+      }
 
-        // 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;
-        }
+      protocol = AppletFormatAdapter.checkProtocol(file);
 
-        if (file.endsWith(".jar"))
+      if (file.endsWith(".jar"))
+      {
+        format = FileFormat.Jalview;
+      }
+      else
+      {
+        try
         {
-          format = FileFormat.Jalview;
-        }
-        else
+          format = new IdentifyFile().identify(file, protocol);
+        } catch (FileFormatException e)
         {
-          try
-          {
-            format = new IdentifyFile().identify(file, protocol);
-          } catch (FileFormatException e)
-          {
-            // TODO what?
-          }
+          // TODO what?
         }
-        af = fileLoader.LoadFileWaitTillLoaded(file, protocol, format);
       }
+
+      af = fileLoader.LoadFileWaitTillLoaded(file, protocol, format);
+       }
     }
     else
     {
@@ -829,7 +885,6 @@ public class Jalview implements ApplicationSingletonI
     }
   }
 
-
   private void setFrameDependentProperties(ArgsParser aparser,
           AlignFrame af)
   {
@@ -915,6 +970,7 @@ public class Jalview implements ApplicationSingletonI
           doUpdateAnnotation = true;
         }
       }
+
     }
 
     if (aparser.contains(ArgsParser.NOSORTBYTREE))
@@ -1080,8 +1136,8 @@ public class Jalview implements ApplicationSingletonI
 
   private static void setLookAndFeel()
   {
-    // property laf = "crossplatform", "system", "gtk", "metal", "nimbus" or
-    // "mac"
+    // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
+    // "mac" or "flat"
     // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
     // try Quaqua/Vaqua.
     String lafProp = System.getProperty("laf");
@@ -1102,62 +1158,69 @@ public class Jalview implements ApplicationSingletonI
       lafSet = setCrossPlatformLookAndFeel();
       if (!lafSet)
       {
-        Cache.log.error("Could not set requested laf=" + laf);
+        Console.error("Could not set requested laf=" + laf);
       }
       break;
     case "system":
       lafSet = setSystemLookAndFeel();
       if (!lafSet)
       {
-        Cache.log.error("Could not set requested laf=" + laf);
+        Console.error("Could not set requested laf=" + laf);
       }
       break;
     case "gtk":
       lafSet = setGtkLookAndFeel();
       if (!lafSet)
       {
-        Cache.log.error("Could not set requested laf=" + laf);
+        Console.error("Could not set requested laf=" + laf);
       }
       break;
     case "metal":
       lafSet = setMetalLookAndFeel();
       if (!lafSet)
       {
-        Cache.log.error("Could not set requested laf=" + laf);
+        Console.error("Could not set requested laf=" + laf);
       }
       break;
     case "nimbus":
       lafSet = setNimbusLookAndFeel();
       if (!lafSet)
       {
-        Cache.log.error("Could not set requested laf=" + laf);
+        Console.error("Could not set requested laf=" + laf);
+      }
+      break;
+    case "flat":
+      lafSet = setFlatLookAndFeel();
+      if (!lafSet)
+      {
+        Console.error("Could not set requested laf=" + laf);
       }
       break;
     case "quaqua":
       lafSet = setQuaquaLookAndFeel();
       if (!lafSet)
       {
-        Cache.log.error("Could not set requested laf=" + laf);
+        Console.error("Could not set requested laf=" + laf);
       }
       break;
     case "vaqua":
       lafSet = setVaquaLookAndFeel();
       if (!lafSet)
       {
-        Cache.log.error("Could not set requested laf=" + laf);
+        Console.error("Could not set requested laf=" + laf);
       }
       break;
     case "mac":
       lafSet = setMacLookAndFeel();
       if (!lafSet)
       {
-        Cache.log.error("Could not set requested laf=" + laf);
+        Console.error("Could not set requested laf=" + laf);
       }
       break;
     case "none":
       break;
     default:
-      Cache.log.error("Requested laf=" + laf + " not implemented");
+      Console.error("Requested laf=" + laf + " not implemented");
     }
     if (!lafSet)
     {
@@ -1183,9 +1246,9 @@ public class Jalview implements ApplicationSingletonI
       set = true;
     } catch (Exception ex)
     {
-      Cache.log.error("Unexpected Look and Feel Exception");
-      Cache.log.error(ex.getMessage());
-      Cache.log.debug(Cache.getStackTraceString(ex));
+      Console.error("Unexpected Look and Feel Exception");
+      Console.error(ex.getMessage());
+      Console.debug(Cache.getStackTraceString(ex));
     }
     return set;
   }
@@ -1199,9 +1262,9 @@ public class Jalview implements ApplicationSingletonI
       set = true;
     } catch (Exception ex)
     {
-      Cache.log.error("Unexpected Look and Feel Exception");
-      Cache.log.error(ex.getMessage());
-      Cache.log.debug(Cache.getStackTraceString(ex));
+      Console.error("Unexpected Look and Feel Exception");
+      Console.error(ex.getMessage());
+      Console.debug(Cache.getStackTraceString(ex));
     }
     return set;
   }
@@ -1217,7 +1280,8 @@ public class Jalview implements ApplicationSingletonI
         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)))
+                : info.getName().toLowerCase(Locale.ROOT)
+                        .equals(name.toLowerCase(Locale.ROOT)))
         {
           className = info.getClassName();
           break;
@@ -1227,9 +1291,9 @@ public class Jalview implements ApplicationSingletonI
       set = true;
     } catch (Exception ex)
     {
-      Cache.log.error("Unexpected Look and Feel Exception");
-      Cache.log.error(ex.getMessage());
-      Cache.log.debug(Cache.getStackTraceString(ex));
+      Console.error("Unexpected Look and Feel Exception");
+      Console.error(ex.getMessage());
+      Console.debug(Cache.getStackTraceString(ex));
     }
     return set;
   }
@@ -1252,6 +1316,44 @@ public class Jalview implements ApplicationSingletonI
             "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
   }
 
+  private static boolean setFlatLookAndFeel()
+  {
+    boolean set = setSpecificLookAndFeel("flatlaf light",
+            "com.formdev.flatlaf.FlatLightLaf", false);
+    if (set)
+    {
+      if (Platform.isMac())
+      {
+        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.getInstance() != null)
+        {
+         Desktop.getInstance().getRootPane()
+                  .putClientProperty("apple.awt.fullWindowContent", true);
+          Desktop.getInstance().getRootPane()
+                  .putClientProperty("apple.awt.transparentTitleBar", true);
+        }
+
+        SwingUtilities.invokeLater(() -> {
+          FlatLightLaf.setup();
+        });
+      }
+
+      UIManager.put("TabbedPane.showTabSeparators", true);
+      UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
+      UIManager.put("TabbedPane.tabsOverlapBorder", true);
+      // UIManager.put("TabbedPane.hasFullBorder", true);
+      UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
+      UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
+      UIManager.put("TabbedPane.smoothScrolling", true);
+      UIManager.put("TabbedPane.tabWidthMode", "compact");
+      UIManager.put("TabbedPane.selectedBackground", Color.white);
+    }
+    return set;
+  }
   private static boolean setQuaquaLookAndFeel()
   {
     return setSpecificLookAndFeel("quaqua",
@@ -1272,14 +1374,19 @@ public class Jalview implements ApplicationSingletonI
     System.setProperty("com.apple.mrj.application.apple.menu.about.name",
             ChannelProperties.getProperty("app_name"));
     System.setProperty("apple.laf.useScreenMenuBar", "true");
+    /*
+     * broken native LAFs on (ARM?) macbooks
     set = setQuaquaLookAndFeel();
     if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
             .toLowerCase(Locale.ROOT).contains("quaqua"))
     {
       set = setVaquaLookAndFeel();
     }
+     */
+    set = setFlatLookAndFeel();
     return set;
   }
+
   private static void showUsage()
   {
     System.out.println(
@@ -1338,17 +1445,17 @@ public class Jalview implements ApplicationSingletonI
               @Override
               public void run()
               {
-                Cache.log.debug(
+                Console.debug(
                         "Initialising googletracker for usage stats.");
                 Cache.initGoogleTracker();
-                Cache.log.debug("Tracking enabled.");
+                Console.debug("Tracking enabled.");
               }
             }, new Runnable()
             {
               @Override
               public void run()
               {
-                Cache.log.debug("Not enabling Google Tracking.");
+                Console.debug("Not enabling Google Tracking.");
               }
             }, null, true);
     desktop.addDialogThread(prompter);