JAL-629 Add a timeout to modal dialogs for command line warning
[jalview.git] / src / jalview / gui / JvOptionPane.java
index 90d812c..0a7c49e 100644 (file)
@@ -88,6 +88,13 @@ public class JvOptionPane extends JOptionPane
 
   private Map<Object, Runnable> callbacks = new HashMap<>();
 
+  private int timeout = -1;
+
+  public void setTimeout(int i)
+  {
+    timeout = i;
+  }
+
   /*
    * JalviewJS reports user choice in the dialog as the selected option (text);
    * this list allows conversion to index (int)
@@ -722,7 +729,8 @@ public class JvOptionPane extends JOptionPane
 
   private static void outputMessage(Object message)
   {
-    System.out.println(">>> JOption Message : " + message.toString());
+    jalview.bin.Console
+            .outPrintln(">>> JOption Message : " + message.toString());
   }
 
   public static Object getMockResponse()
@@ -850,6 +858,38 @@ public class JvOptionPane extends JOptionPane
                   "Supplied buttons array not the same length as supplied options array.");
           break NOTNULL;
         }
+
+        // run through buttons for initialValue first so can set a final
+        // timeoutThreadF
+        Thread timeoutThread = null;
+        for (int i = 0; i < options.length; i++)
+        {
+          Object o = options[i];
+          JButton jb = buttons[i];
+          if (o.equals(initialValue))
+          {
+            initialValueButton = jb;
+            if (timeout > 0 && initialValueButton != null
+                    && initialValueButton instanceof JButton)
+            {
+              Runnable timeoutClose = () -> {
+                try
+                {
+                  Thread.sleep(timeout);
+                } catch (InterruptedException e)
+                {
+                  Console.debug(
+                          "Dialog timeout interrupted.  Probably a button pressed.");
+                }
+                jb.doClick();
+              };
+              timeoutThread = new Thread(timeoutClose);
+            }
+          }
+        }
+        final Thread timeoutThreadF = timeoutThread;
+        timeoutThreadF.start();
+
         int[] buttonActions = { JOptionPane.YES_OPTION,
             JOptionPane.NO_OPTION, JOptionPane.CANCEL_OPTION };
         for (int i = 0; i < options.length; i++)
@@ -859,9 +899,6 @@ public class JvOptionPane extends JOptionPane
                   "Setting button " + i + " to '" + o.toString() + "'");
           JButton jb = buttons[i];
 
-          if (o.equals(initialValue))
-            initialValueButton = jb;
-
           int buttonAction = buttonActions[i];
           Runnable action = callbacks.get(buttonAction);
           jb.setText((String) o);
@@ -870,6 +907,10 @@ public class JvOptionPane extends JOptionPane
             @Override
             public void actionPerformed(ActionEvent e)
             {
+              if (timeoutThreadF != null)
+              {
+                timeoutThreadF.interrupt();
+              }
 
               Object obj = e.getSource();
               if (obj == null || !(obj instanceof Component))
@@ -1141,7 +1182,13 @@ public class JvOptionPane extends JOptionPane
 
   private void internalDialogHandleResponse()
   {
-    String responseString = (String) this.getValue();
+    Object value = this.getValue();
+    if (value == null
+            || (value instanceof Integer && (Integer) value == -1))
+    {
+      return;
+    }
+    String responseString = value.toString();
     int response = ourOptions.indexOf(responseString);
 
     if (!Platform.isJS())
@@ -1258,6 +1305,17 @@ public class JvOptionPane extends JOptionPane
           int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options,
           Object initialValue, boolean modal, JButton[] buttons)
   {
+    showDialogOnTopAsync(dialogParent, label, actionString,
+            JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options,
+            initialValue, modal, buttons, true);
+  }
+
+  public void showDialogOnTopAsync(JFrame dialogParent, Object label,
+          String actionString, int JOPTIONPANE_OPTION,
+          int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options,
+          Object initialValue, boolean modal, JButton[] buttons,
+          boolean dispose)
+  {
     if (!isInteractiveMode())
     {
       handleResponse(getMockResponse());
@@ -1279,8 +1337,11 @@ public class JvOptionPane extends JOptionPane
             JOPTIONPANE_MESSAGETYPE, icon, options, initialValue, modal,
             buttons);
 
-    dialogParent.setAlwaysOnTop(false);
-    dialogParent.dispose();
+    if (dispose)
+    {
+      dialogParent.setAlwaysOnTop(false);
+      dialogParent.dispose();
+    }
   }
 
   /**