JAL-4442 Add a wait for termination of button action handlers method
authorBen Soares <b.soares@dundee.ac.uk>
Mon, 12 Aug 2024 19:47:33 +0000 (20:47 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Mon, 12 Aug 2024 19:47:33 +0000 (20:47 +0100)
src/jalview/gui/JvOptionPane.java
src/jalview/gui/QuitHandler.java

index 7a5daf7..726e942 100644 (file)
@@ -1,14 +1,14 @@
 /*
  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
  * Copyright (C) $$Year-Rel$$ The Jalview Authors
- * 
+ *
  * This file is part of Jalview.
- * 
+ *
  * Jalview is free software: you can redistribute it and/or
  * modify it under the terms of the GNU General Public License 
  * as published by the Free Software Foundation, either version 3
  * of the License, or (at your option) any later version.
- *  
+ *
  * Jalview is distributed in the hope that it will be useful, but 
  * WITHOUT ANY WARRANTY; without even the implied warranty 
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
@@ -45,6 +45,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
 
 import javax.swing.Icon;
 import javax.swing.JButton;
@@ -784,7 +785,7 @@ public class JvOptionPane extends JOptionPane
   /**
    * create a new option dialog that can be used to register responses - along
    * lines of showOptionDialog
-   * 
+   *
    * @param desktop
    * @param question
    * @param string
@@ -985,10 +986,11 @@ public class JvOptionPane extends JOptionPane
       if (!Platform.isJS())
       /**
        * Java only
-       * 
+       *
        * @j2sIgnore
        */
       {
+        Console.debug("Handling response for " + response);
         handleResponse(response);
       }
     }
@@ -1198,7 +1200,7 @@ public class JvOptionPane extends JOptionPane
     if (!Platform.isJS())
     /**
      * Java only
-     * 
+     *
      * @j2sIgnore
      */
     {
@@ -1209,7 +1211,7 @@ public class JvOptionPane extends JOptionPane
   /*
    * @Override public JvOptionPane setResponseHandler(Object response, Runnable
    * action) { callbacks.put(response, new Callable<Void>() {
-   * 
+   *
    * @Override public Void call() { action.run(); return null; } }); return this;
    * }
    */
@@ -1355,7 +1357,7 @@ public class JvOptionPane extends JOptionPane
    * JalviewJS signals option selection by a property change event for the
    * option e.g. "OK". This methods responds to that by running the response
    * action that corresponds to that option.
-   * 
+   *
    * @param evt
    */
   @Override
@@ -1389,7 +1391,8 @@ public class JvOptionPane extends JOptionPane
     {
       try
       {
-        new Thread(action).start();
+        executor.submit(action);
+        // new Thread(action).start();
         // action.call();
       } catch (Exception e)
       {
@@ -1542,7 +1545,7 @@ public class JvOptionPane extends JOptionPane
 
   /**
    * Utility to programmatically click a button on a JOptionPane (as a JFrame)
-   * 
+   *
    * returns true if button was found
    */
   public static boolean clickButton(JFrame frame, int buttonType)
@@ -1751,4 +1754,26 @@ public class JvOptionPane extends JOptionPane
     }
   }
 
+  private static final long defaultTimeout = 500;
+
+  public boolean waitForHandlerToFinish()
+  {
+    return waitForHandlerToFinish(defaultTimeout);
+  }
+
+  public boolean waitForHandlerToFinish(long timeout)
+  {
+    if (executor != null)
+    {
+      try
+      {
+        return executor.awaitTermination(timeout, TimeUnit.MILLISECONDS);
+      } catch (InterruptedException e)
+      {
+        Console.debug("Action was interrupted", e);
+      }
+    }
+    return true;
+  }
+
 }
index 1b48c6d..9917222 100644 (file)
@@ -1,14 +1,14 @@
 /*
  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
  * Copyright (C) $$Year-Rel$$ The Jalview Authors
- * 
+ *
  * This file is part of Jalview.
- * 
+ *
  * Jalview is free software: you can redistribute it and/or
  * modify it under the terms of the GNU General Public License 
  * as published by the Free Software Foundation, either version 3
  * of the License, or (at your option) any later version.
- *  
+ *
  * Jalview is distributed in the hope that it will be useful, but 
  * WITHOUT ANY WARRANTY; without even the implied warranty 
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
@@ -95,10 +95,12 @@ public class QuitHandler
 
   protected static QResponse setResponse(QResponse qresponse)
   {
+    Console.debug("setResponse(" + qresponse.toString() + ")");
     gotQuitResponse = qresponse;
     if ((qresponse == QResponse.CANCEL_QUIT || qresponse == QResponse.NULL)
             && flatlafResponse != null)
     {
+      Console.debug("Running flatLafResponse.cancelQuit()");
       flatlafResponse.cancelQuit();
     }
     return qresponse;
@@ -137,9 +139,13 @@ public class QuitHandler
           Runnable forceQuit, Runnable cancelQuit)
   {
     QResponse got = gotQuitResponse();
+    Console.debug("Quit response is '" + got.toString()
+            + "' at start of getQuitResponse(...)");
     if (got != QResponse.NULL && got != QResponse.CANCEL_QUIT)
     {
       // quit has already been selected, continue with calling quit method
+      Console.debug("Returning already set quit response of '"
+              + got.toString() + "' at start of getQuitResponse(...)");
       return got;
     }
 
@@ -162,13 +168,17 @@ public class QuitHandler
       confirmQuit = jalview.bin.Cache
               .getDefault(jalview.gui.Desktop.CONFIRM_KEYBOARD_QUIT, true);
       Console.debug("Jalview property '"
-              + jalview.gui.Desktop.CONFIRM_KEYBOARD_QUIT
-              + "' is/defaults to " + confirmQuit + " -- "
-              + (confirmQuit ? "" : "not ") + "confirming quit");
+              + jalview.gui.Desktop.CONFIRM_KEYBOARD_QUIT + "' is "
+              + confirmQuit + " -- " + (confirmQuit ? "" : "not ")
+              + "confirming quit");
     }
+
     got = confirmQuit ? QResponse.NULL : QResponse.QUIT;
     setResponse(got);
 
+    Console.debug("confirmQuit is '" + confirmQuit
+            + "', setting quit response to " + got);
+
     if (confirmQuit)
     {
       String messageString = MessageManager
@@ -182,17 +192,21 @@ public class QuitHandler
       qd.showDialogOnTopAsync(
               new StringBuilder(
                       MessageManager.getString("label.quit_jalview"))
-                              .append("\n").append(messageString)
-                              .toString(),
+                      .append("\n").append(messageString).toString(),
               MessageManager.getString("action.quit"),
               JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null,
               new Object[]
               { MessageManager.getString("action.quit"),
                   MessageManager.getString("action.cancel") },
               MessageManager.getString("action.quit"), true);
+
+      Console.debug("Waiting for response handler to run action");
+      qd.waitForHandlerToFinish();
     }
 
     got = gotQuitResponse();
+    Console.debug("Quit response is '" + got.toString()
+            + "' after response handler");
 
     // check for external viewer frames
     if (got != QResponse.CANCEL_QUIT)
@@ -246,6 +260,9 @@ public class QuitHandler
 
     got = gotQuitResponse();
 
+    Console.debug("Quit response is '" + got.toString()
+            + "' after external structure viewer check");
+
     boolean wait = false;
     if (got == QResponse.CANCEL_QUIT)
     {
@@ -257,6 +274,8 @@ public class QuitHandler
     }
     else if (got == QResponse.QUIT)
     {
+      Console.debug("Quit response is '" + got.toString()
+              + "' before waiting for save");
       if (Cache.getDefault("WAIT_FOR_SAVE", true)
               && BackupFiles.hasSavesInProgress())
       {
@@ -264,25 +283,40 @@ public class QuitHandler
         QResponse waitResponse = gotQuitResponse();
         wait = waitResponse == QResponse.QUIT;
       }
+      Console.debug("Quit response is '" + got.toString()
+              + "' after waiting for save");
     }
 
     Runnable next = null;
+    String nextName = null;
+    got = gotQuitResponse();
+    Console.debug("Quit response is '" + got.toString()
+            + "' before setting next");
     switch (gotQuitResponse())
     {
     case QUIT:
       next = okQuit;
+      nextName = "okQuit";
       break;
     case FORCE_QUIT: // not actually an option at this stage
       next = forceQuit;
+      nextName = "forceQuit";
       break;
     default:
       next = cancelQuit;
+      nextName = "cancelQuit";
       break;
     }
+    Console.debug(
+            "Quit response is '" + got.toString() + "' after setting next");
+    Console.debug("Next is '" + next + "'");
     try
     {
       executor.submit(next).get();
+      Console.debug(next + " is submitted");
       got = gotQuitResponse();
+      Console.debug("Quit response is '" + got.toString()
+              + "' after submitting next");
     } catch (RejectedExecutionException e)
     {
       // QuitHander.abortQuit() probably called
@@ -295,16 +329,23 @@ public class QuitHandler
       jalview.bin.Console
               .debug("Exception during quit handling (final choice)", e);
     }
+    Console.debug("Setting response to '" + got.toString()
+            + "' after submitting next");
     setResponse(got);
 
+    Console.debug("Checking if quit was cancelled");
     if (quitCancelled())
     {
       // reset if cancelled
       Console.debug("Quit cancelled");
       setResponse(QResponse.NULL);
+      Console.debug("Set response to " + QResponse.NULL.toString()
+              + ". Returning " + QResponse.CANCEL_QUIT);
       return QResponse.CANCEL_QUIT;
     }
-    return gotQuitResponse();
+    got = gotQuitResponse();
+    Console.debug("Returning " + got.toString());
+    return got;
   }
 
   private static QResponse waitQuit(boolean interactive, Runnable okQuit,