JAL-629 Add a timeout to modal dialogs for command line warning
[jalview.git] / src / jalview / bin / Jalview.java
index e229079..ba418fe 100755 (executable)
@@ -76,6 +76,7 @@ import jalview.bin.argparser.BootstrapArgs;
 import jalview.ext.so.SequenceOntology;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
 import jalview.gui.PromptUserConfig;
 import jalview.gui.QuitHandler;
 import jalview.gui.QuitHandler.QResponse;
@@ -139,9 +140,9 @@ public class Jalview
 
   public static AlignFrame currentAlignFrame;
 
-  public ArgParser argparser = null;
+  private ArgParser argparser = null;
 
-  public BootstrapArgs bootstrapArgs = null;
+  private BootstrapArgs bootstrapArgs = null;
 
   private boolean QUIET = false;
 
@@ -426,7 +427,7 @@ public class Jalview
     // stop now if only after --version
     if (bootstrapArgs.contains(Arg.VERSION))
     {
-      Jalview.exit(null, 0);
+      Jalview.exit(null, ExitCode.OK);
     }
 
     // old ArgsParser
@@ -458,7 +459,7 @@ public class Jalview
       error.printStackTrace();
       String message = "\nEssential logging libraries not found."
               + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
-      Jalview.exit(message, 0);
+      Jalview.exit(message, ExitCode.OK);
     }
 
     // register SIGTERM listener
@@ -545,7 +546,7 @@ public class Jalview
                 .getList(Arg.HELP);
         Console.outPrintln(Arg.usage(helpArgs.stream().map(e -> e.getKey())
                 .collect(Collectors.toList())));
-        Jalview.exit(null, 0);
+        Jalview.exit(null, ExitCode.OK);
       }
       if (aparser.contains("help") || aparser.contains("h"))
       {
@@ -554,7 +555,7 @@ public class Jalview
         showUsage();
         */
         Console.outPrintln(Arg.usage());
-        Jalview.exit(null, 0);
+        Jalview.exit(null, ExitCode.OK);
       }
 
       // new CLI
@@ -641,14 +642,12 @@ public class Jalview
     try
     {
       Console.initLogger();
-    } catch (
-
-    NoClassDefFoundError error)
+    } catch (NoClassDefFoundError error)
     {
       error.printStackTrace();
       String message = "\nEssential logging libraries not found."
               + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
-      Jalview.exit(message, 0);
+      Jalview.exit(message, ExitCode.NO_LOGGING);
     }
     desktop = null;
 
@@ -673,6 +672,8 @@ public class Jalview
       desktop = new Desktop();
       desktop.setInBatchMode(true); // indicate we are starting up
 
+      mixedCliWarning();
+
       try
       {
         JalviewTaskbar.setTaskbar(this);
@@ -809,8 +810,33 @@ public class Jalview
         }
       }
     }
+    else
+    {
+
+      if (getArgParser().isMixedStyle())
+      {
+        String warning = MessageManager.formatMessage(
+                "warning.using_mixed_command_line_arguments",
+                getArgParser().getMixedExamples());
+        Console.warn(warning);
+        Jalview.exit(
+                "Exiting due to mixed old and new command line arguments",
+                ExitCode.INVALID_ARGUMENT);
+      }
+      if (getArgParser().isOldStyle())
+      {
+        String warning = MessageManager
+                .getString("warning.using_old_command_line_arguments")
+                .replace("\n", " ")
+                + "https://www.jalview.org/help/html/features/commandline.html";
+        Console.warn(warning);
+      }
+
+    }
+
     // Run Commands from cli
     cmds = new Commands(argparser, headlessArg);
+    cmds.processArgs();
     boolean commandsSuccess = cmds.argsWereParsed();
 
     if (commandsSuccess)
@@ -826,7 +852,7 @@ public class Jalview
         else
         {
           Jalview.exit("Successfully completed commands in headless mode",
-                  0);
+                  ExitCode.OK);
         }
       }
       Console.info("Successfully completed commands");
@@ -835,7 +861,8 @@ public class Jalview
     {
       if (headlessArg)
       {
-        Jalview.exit("Error when running Commands in headless mode", 1);
+        Jalview.exit("Error when running Commands in headless mode",
+                ExitCode.ERROR_RUNNING_COMMANDS);
       }
       Console.warn("Error when running commands");
     }
@@ -866,7 +893,7 @@ public class Jalview
 
     if (file == null && desktop == null && !commandsSuccess)
     {
-      Jalview.exit("No files to open!", 1);
+      Jalview.exit("No files to open!", ExitCode.NO_FILES);
     }
 
     long progress = -1;
@@ -896,7 +923,8 @@ public class Jalview
             if (headless)
             {
               Jalview.exit(
-                      "Can't find file '" + file + "' in headless mode", 1);
+                      "Can't find file '" + file + "' in headless mode",
+                      ExitCode.FILE_NOT_FOUND);
             }
             Console.warn("Can't find file'" + file + "'");
           }
@@ -1220,6 +1248,8 @@ public class Jalview
       }
       desktop.setInBatchMode(false);
     }
+
+    cliWarning();
   }
 
   private static void setLookAndFeel()
@@ -1501,7 +1531,7 @@ public class Jalview
       UIManager.put("TabbedPane.tabType", "card");
       UIManager.put("TabbedPane.showTabSeparators", true);
       UIManager.put("TabbedPane.showContentSeparator", true);
-      UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
+      // UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
       UIManager.put("TabbedPane.tabsOverlapBorder", true);
       UIManager.put("TabbedPane.hasFullBorder", true);
       UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
@@ -1600,9 +1630,8 @@ public class Jalview
      */
     PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
             "USAGESTATS",
-            MessageManager.getString("prompt.plausible_analytics_title"),
-            MessageManager.getString("prompt.plausible_analytics"),
-            new Runnable()
+            MessageManager.getString("prompt.analytics_title"),
+            MessageManager.getString("prompt.analytics"), new Runnable()
             {
               @Override
               public void run()
@@ -1768,7 +1797,7 @@ public class Jalview
   public void quit()
   {
     // System.exit will run the shutdownHook first
-    Jalview.exit("Quitting now. Bye!", 0);
+    Jalview.exit("Quitting now. Bye!", ExitCode.OK);
   }
 
   public static AlignFrame getCurrentAlignFrame()
@@ -1781,13 +1810,14 @@ public class Jalview
     Jalview.currentAlignFrame = currentAlignFrame;
   }
 
-  protected Commands getCommands()
+  public Commands getCommands()
   {
     return cmds;
   }
 
-  public static void exit(String message, int exitcode)
+  public static void exit(String message, ExitCode ec)
   {
+    int exitcode = ec == ExitCode.OK ? 0 : ec.ordinal() + 1;
     if (Console.log == null)
     {
       // Don't start the logger just to exit!
@@ -1824,14 +1854,35 @@ public class Jalview
     }
   }
 
+  public enum ExitCode
+  {
+    // only add new ones to the end of the list (to preserve ordinal values)
+    OK, FILE_NOT_FOUND, FILE_NOT_READABLE, NO_FILES, INVALID_FORMAT,
+    INVALID_ARGUMENT, INVALID_VALUE, MIXED_CLI_ARGUMENTS,
+    ERROR_RUNNING_COMMANDS, NO_LOGGING;
+  }
+
   /******************************
    * 
    * TEST OUTPUT METHODS
    * 
+   * these operate only when Arg.TESTOUTPUT has been passed, and variously check
+   * if an expected value / arg was set and report it to the test framework.
+   * 
    ******************************/
   /**
-   * method for reporting string values parsed/processed during tests
+   * report string values parsed/processed during tests When the Bootstrap
+   * argument Arg.TESTOUTPUT is present - reports on debug if given s1 is not
+   * null and not equals s2, warns if given argument is not set, and calls
+   * testoutput(true,a,s1,s2) to report processing progress.
    * 
+   * @param ap
+   *          - ArgParser handling parsing
+   * @param a
+   *          - Arg currently being processed
+   * @param s1
+   *          - expected
+   * @param s2
    */
   protected static void testoutput(ArgParser ap, Arg a, String s1,
           String s2)
@@ -1856,7 +1907,9 @@ public class Jalview
   }
 
   /**
-   * method for reporting string values parsed/processed during tests
+   * report values passed via bootstrap arguments
+   * 
+   * TODO: significant code duplication with testouput(Argparser...) - move it
    */
 
   protected static void testoutput(BootstrapArgs bsa, Arg a, String s1,
@@ -1884,7 +1937,8 @@ public class Jalview
   }
 
   /**
-   * report value set for string values parsed/processed during tests
+   * conditionally (on @param yes) report that expected value s1 was set during
+   * CommandsTest tests
    */
   private static void testoutput(boolean yes, Arg a, String s1, String s2)
   {
@@ -1951,4 +2005,88 @@ public class Jalview
     }
     Console.outPrintln("[TESTOUTPUT] arg " + message);
   }
+
+  public ArgParser getArgParser()
+  {
+    return argparser;
+  }
+
+  public BootstrapArgs getBootstrapArgs()
+  {
+    return bootstrapArgs;
+  }
+
+  public static boolean isBatchMode()
+  {
+    return getInstance() != null && (getInstance().desktop == null
+            || getInstance().desktop.isInBatchMode());
+  }
+
+  /**
+   * Warning about old or mixed command line arguments
+   */
+  private void mixedCliWarning()
+  {
+    Jalview j = Jalview.getInstance();
+    boolean mixedStyle = j.getArgParser() != null
+            && j.getArgParser().isMixedStyle();
+    String title = MessageManager.getString("label.command_line_arguments");
+    if (mixedStyle)
+    {
+      String warning = MessageManager.formatMessage(
+              "warning.using_mixed_command_line_arguments",
+              j.getArgParser().getMixedExamples());
+      String quit = MessageManager.getString("action.quit");
+
+      Desktop.instance.nonBlockingDialog(title, warning, null, quit,
+              JvOptionPane.WARNING_MESSAGE, false, false, true, 30000);
+
+      Jalview.exit(
+              "Exiting due to mixed old and new command line arguments.",
+              ExitCode.MIXED_CLI_ARGUMENTS);
+    }
+  }
+
+  private void cliWarning()
+  {
+    Jalview j = Jalview.getInstance();
+    Commands c = j.getCommands();
+    boolean oldStyle = j.getArgParser() != null
+            && j.getArgParser().isOldStyle();
+    String title = MessageManager.getString("label.command_line_arguments");
+    if (oldStyle)
+    {
+      String warning = MessageManager
+              .getString("warning.using_old_command_line_arguments");
+      String url = "<a href=\"https://www.jalview.org/help/html/features/commandline.html\">https://www.jalview.org/help/html/features/commandline.html</a>";
+      if (Desktop.instance != null)
+      {
+        String cont = MessageManager.getString("label.continue");
+
+        Desktop.instance.nonBlockingDialog(title, warning, url, cont,
+                JvOptionPane.WARNING_MESSAGE, false, true, true, 2000);
+      }
+    }
+    if (j.getCommands() != null && j.getCommands().getErrors().size() > 0)
+    {
+      if (Desktop.instance != null)
+      {
+        String message = MessageManager
+                .getString("warning.the_following_errors");
+        String ok = MessageManager.getString("action.ok");
+        int shortest = 60;
+        List<String> errors = j.getCommands().getErrors();
+        for (int i = 0; i < errors.size(); i++)
+        {
+          shortest = Math.min(shortest, errors.get(i).length());
+        }
+        Desktop.instance.nonBlockingDialog(
+                Math.max(message.length(), Math.min(60, shortest)),
+                Math.min(errors.size(), 20), title, message,
+                j.getCommands().errorsToString(), ok,
+                JvOptionPane.WARNING_MESSAGE, true, false, true, -1);
+      }
+    }
+  }
+
 }