JAL-4059 Revert libjs/MiGLayout as new miglayout transpile of 4.0 includes reference...
[jalview.git] / src / jalview / gui / Desktop.java
index d5840e6..5a8c048 100644 (file)
@@ -114,6 +114,8 @@ import jalview.bin.Cache;
 import jalview.bin.Jalview;
 import jalview.bin.Jalview.ExitCode;
 import jalview.bin.argparser.Arg;
+import jalview.bin.groovy.JalviewObject;
+import jalview.bin.groovy.JalviewObjectI;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.Sequence;
@@ -139,6 +141,8 @@ import jalview.structure.StructureSelectionManager;
 import jalview.urls.IdOrgSettings;
 import jalview.util.BrowserLauncher;
 import jalview.util.ChannelProperties;
+import jalview.util.IdUtils;
+import jalview.util.IdUtils.IdType;
 import jalview.util.ImageMaker.TYPE;
 import jalview.util.LaunchUtils;
 import jalview.util.MessageManager;
@@ -158,7 +162,7 @@ import jalview.ws.utils.UrlDownloadClient;
  */
 public class Desktop extends jalview.jbgui.GDesktop
         implements DropTargetListener, ClipboardOwner, IProgressIndicator,
-        jalview.api.StructureSelectionManagerProvider
+        jalview.api.StructureSelectionManagerProvider, JalviewObjectI
 {
   private static final String CITATION;
   static
@@ -182,7 +186,7 @@ public class Desktop extends jalview.jbgui.GDesktop
             : "&nbsp;<img alt=\"University of Dundee shield\" src=\""
                     + uod_logo_url.toString() + "\">");
     sb.append(
-            "<br><br>For help, see <a href=\"https://www.jalview.org/faq\">www.jalview.org/faq</a> and join <a href=\"https://discourse.jalview.org\">discourse.jalview.org</a>");
+            "<br><br>For help, see <a href=\"https://www.jalview.org/help/faq\">www.jalview.org/faq</a> and join <a href=\"https://discourse.jalview.org\">discourse.jalview.org</a>");
     sb.append("<br><br>If  you use Jalview, please cite:"
             + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
             + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
@@ -446,8 +450,8 @@ public class Desktop extends jalview.jbgui.GDesktop
       if (LaunchUtils.getJavaVersion() >= 11)
       {
         /*
-         * Send this message to stderr as the warning that follows (due to
-         * reflection) also goes to stderr.
+         * Send this message to stderr as the warning that follows (due to reflection)
+         * also goes to stderr.
          */
         jalview.bin.Console.errPrintln(
                 "Linux platform only! You may have the following warning next: \"WARNING: An illegal reflective access operation has occurred\"\nThis is expected and cannot be avoided, sorry about that.");
@@ -547,12 +551,10 @@ public class Desktop extends jalview.jbgui.GDesktop
             Platform.isJS() ? desktop.getDesktopManager()
                     : new DefaultDesktopManager()));
     /*
-    (Platform.isWindowsAndNotJS() ? new DefaultDesktopManager()
-            : Platform.isAMacAndNotJS()
-                    ? new AquaInternalFrameManager(
-                            desktop.getDesktopManager())
-                    : desktop.getDesktopManager())));
-                    */
+     * (Platform.isWindowsAndNotJS() ? new DefaultDesktopManager() :
+     * Platform.isAMacAndNotJS() ? new AquaInternalFrameManager(
+     * desktop.getDesktopManager()) : desktop.getDesktopManager())));
+     */
 
     Rectangle dims = getLastKnownDimensions("");
     if (dims != null)
@@ -654,6 +656,22 @@ public class Desktop extends jalview.jbgui.GDesktop
 
     if (Platform.isJS())
     {
+      String ns = Jalview.getInstance().getJSNamespace();
+      if (ns != null)
+      {
+
+        String nsc = ns + (ns.length() > 0 ? ":" : "");
+        String splashId = nsc + "jalviewSplash";
+        /**
+         * @j2sNative let splash = document.getElementById(splashId);
+         * 
+         *            if (splash != null) {
+         * 
+         *            splash.style.display = "none";
+         * 
+         *            }
+         */
+      }
       // used for jalviewjsTest
       jalview.bin.Console.info("JALVIEWJS: CREATED DESKTOP");
     }
@@ -757,11 +775,12 @@ public class Desktop extends jalview.jbgui.GDesktop
         @Override
         public void run()
         {
-          long now = System.currentTimeMillis();
+          long progressId = IdUtils.newId(IdType.PROGRESS);
           Desktop.instance.setProgressBar(
-                  MessageManager.getString("status.refreshing_news"), now);
+                  MessageManager.getString("status.refreshing_news"),
+                  progressId);
           jvnews.refreshNews();
-          Desktop.instance.setProgressBar(null, now);
+          Desktop.instance.setProgressBar(null, progressId);
           jvnews.showNews();
         }
       }).start();
@@ -1056,7 +1075,7 @@ public class Desktop extends jalview.jbgui.GDesktop
         {
           if (itf instanceof AlignFrame)
           {
-            Jalview.setCurrentAlignFrame((AlignFrame) itf);
+            Jalview.getInstance().setCurrentAlignFrame((AlignFrame) itf);
           }
           itf.requestFocus();
         }
@@ -1283,7 +1302,7 @@ public class Desktop extends jalview.jbgui.GDesktop
       }
     }
     evt.dropComplete(success); // need this to ensure input focus is properly
-                               // transfered to any new windows created
+    // transfered to any new windows created
   }
 
   /**
@@ -1475,62 +1494,81 @@ public class Desktop extends jalview.jbgui.GDesktop
     desktopQuit(true, false);
   }
 
-  public QuitHandler.QResponse desktopQuit(boolean ui, boolean disposeFlag)
+  /**
+   * close everything, stash window geometries, and shut down all associated
+   * threads/workers
+   * 
+   * @param dispose
+   *          - sets the dispose on close flag - JVM may terminate when set
+   * @param terminateJvm
+   *          - quit with prejudice - stops the JVM.
+   */
+  public void quitTheDesktop(boolean dispose, boolean terminateJvm)
   {
-    final Runnable doDesktopQuit = () -> {
-      Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
-      Cache.setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
-      Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height + "");
-      storeLastKnownDimensions("", new Rectangle(getBounds().x,
-              getBounds().y, getWidth(), getHeight()));
+    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+    Cache.setProperty("SCREENGEOMETRY_WIDTH", screen.width + "");
+    Cache.setProperty("SCREENGEOMETRY_HEIGHT", screen.height + "");
+    storeLastKnownDimensions("", new Rectangle(getBounds().x, getBounds().y,
+            getWidth(), getHeight()));
 
-      if (jconsole != null)
-      {
-        storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
-        jconsole.stopConsole();
-      }
+    if (jconsole != null)
+    {
+      storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds());
+      jconsole.stopConsole();
+    }
 
-      if (jvnews != null)
-      {
-        storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
-      }
+    if (jvnews != null)
+    {
+      storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds());
+    }
 
-      // Frames should all close automatically. Keeping external
-      // viewers open should already be decided by user.
-      closeAll_actionPerformed(null);
+    // Frames should all close automatically. Keeping external
+    // viewers open should already be decided by user.
+    closeAll_actionPerformed(null);
 
-      // check for aborted quit
-      if (QuitHandler.quitCancelled())
-      {
-        jalview.bin.Console.debug("Desktop aborting quit");
-        return;
-      }
+    if (dialogExecutor != null)
+    {
+      dialogExecutor.shutdownNow();
+    }
 
-      if (dialogExecutor != null)
-      {
-        dialogExecutor.shutdownNow();
-      }
+    if (groovyConsole != null)
+    {
+      // suppress a possible repeat prompt to save script
+      groovyConsole.setDirty(false);
+      groovyConsole.exit();
+    }
 
-      if (groovyConsole != null)
-      {
-        // suppress a possible repeat prompt to save script
-        groovyConsole.setDirty(false);
-        groovyConsole.exit();
-      }
+    if (terminateJvm)
+    {
+      // note that shutdown hook will not be run
+      jalview.bin.Console.debug("Force Quit selected by user");
+      Runtime.getRuntime().halt(0);
+    }
 
-      if (QuitHandler.gotQuitResponse() == QResponse.FORCE_QUIT)
-      {
-        // note that shutdown hook will not be run
-        jalview.bin.Console.debug("Force Quit selected by user");
-        Runtime.getRuntime().halt(0);
-      }
+    jalview.bin.Console.debug("Quit selected by user");
+    if (dispose)
+    {
+      instance.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+      // instance.dispose();
+    }
+  }
+
+  public QuitHandler.QResponse desktopQuit(boolean ui, boolean disposeFlag)
+  {
+    final Runnable doDesktopQuit = () -> {
 
-      jalview.bin.Console.debug("Quit selected by user");
-      if (disposeFlag)
+      // FIRST !! check for aborted quit
+      if (QuitHandler.quitCancelled())
       {
-        instance.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
-        // instance.dispose();
+        jalview.bin.Console
+                .debug("Quit was cancelled - Desktop aborting quit");
+        return;
       }
+
+      // Proceed with quitting
+      quitTheDesktop(disposeFlag,
+              QuitHandler.gotQuitResponse() == QResponse.FORCE_QUIT);
+      // and exit the JVM
       instance.quit();
     };
 
@@ -1539,7 +1577,14 @@ public class Desktop extends jalview.jbgui.GDesktop
   }
 
   /**
-   * Don't call this directly, use desktopQuit() above. Exits the program.
+   * Exits the program and the JVM.
+   * 
+   * Don't call this directly
+   * 
+   * - use desktopQuit() above to tidy up first.
+   * 
+   * - use closeDesktop() to shutdown Jalview without shutting down the JVM
+   * 
    */
   @Override
   public void quit()
@@ -1679,7 +1724,7 @@ public class Desktop extends jalview.jbgui.GDesktop
       {
       }
     }
-    Jalview.setCurrentAlignFrame(null);
+    Jalview.getInstance().setCurrentAlignFrame(null);
     jalview.bin.Console.info("ALL CLOSED");
 
     /*
@@ -1928,7 +1973,8 @@ public class Desktop extends jalview.jbgui.GDesktop
           // TODO: refactor to Jalview desktop session controller action.
           setProgressBar(MessageManager.formatMessage(
                   "label.saving_jalview_project", new Object[]
-                  { chosenFile.getName() }), chosenFile.hashCode());
+                  { chosenFile.getName() }),
+                  IdUtils.newId(IdType.PROGRESS, chosenFile));
           Cache.setProperty("LAST_DIRECTORY", chosenFile.getParent());
           // TODO catch and handle errors for savestate
           // TODO prevent user from messing with the Desktop whilst we're saving
@@ -1962,7 +2008,7 @@ public class Desktop extends jalview.jbgui.GDesktop
                     MessageManager.getString("label.couldnt_save_project"),
                     JvOptionPane.WARNING_MESSAGE);
           }
-          setProgressBar(null, chosenFile.hashCode());
+          setProgressBar(null, IdUtils.newId(IdType.PROGRESS, chosenFile));
         }
       }).start();
     }
@@ -1997,8 +2043,8 @@ public class Desktop extends jalview.jbgui.GDesktop
     JalviewFileChooser chooser = new JalviewFileChooser(
             Cache.getProperty("LAST_DIRECTORY"), suffix, desc,
             "Jalview Project", true, BackupFiles.getEnabled()); // last two
-                                                                // booleans:
-                                                                // allFiles,
+    // booleans:
+    // allFiles,
     // allowBackupFiles
     chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
@@ -2138,7 +2184,7 @@ public class Desktop extends jalview.jbgui.GDesktop
       return null;
     }
     List<AlignmentPanel> aps = new ArrayList<>();
-    AlignFrame[] frames = getAlignFrames();
+    AlignFrame[] frames = Desktop.getDesktopAlignFrames();
     if (frames == null)
     {
       return null;
@@ -2175,7 +2221,7 @@ public class Desktop extends jalview.jbgui.GDesktop
     List<AlignmentViewport> viewp = new ArrayList<>();
     if (desktop != null)
     {
-      AlignFrame[] frames = Desktop.getAlignFrames();
+      AlignFrame[] frames = Desktop.getDesktopAlignFrames();
 
       for (AlignFrame afr : frames)
       {
@@ -2536,12 +2582,12 @@ public class Desktop extends jalview.jbgui.GDesktop
    * 
    * @return an array of AlignFrame, or null if none found
    */
-  public static AlignFrame[] getAlignFrames()
+  @Override
+  public AlignFrame[] getAlignFrames()
   {
-    if (Jalview.isHeadlessMode())
+    if (desktop == null)
     {
-      // Desktop.desktop is null in headless mode
-      return new AlignFrame[] { Jalview.currentAlignFrame };
+      return null;
     }
 
     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
@@ -2583,6 +2629,25 @@ public class Desktop extends jalview.jbgui.GDesktop
   }
 
   /**
+   * static version
+   */
+  public static AlignFrame[] getDesktopAlignFrames()
+  {
+    if (Jalview.isHeadlessMode())
+    {
+      // Desktop.desktop is null in headless mode
+      return Jalview.getInstance().getAlignFrames();
+    }
+
+    if (instance != null && desktop != null)
+    {
+      return instance.getAlignFrames();
+    }
+
+    return null;
+  }
+
+  /**
    * Returns an array of any AppJmol frames in the Desktop (or null if none).
    * 
    * @return
@@ -2624,7 +2689,7 @@ public class Desktop extends jalview.jbgui.GDesktop
       openGroovyConsole();
     } catch (Exception ex)
     {
-      jalview.bin.Console.error("Groovy Shell Creation failed.", ex);
+      jalview.bin.Console.error("Groovy Console creation failed.", ex);
       JvOptionPane.showInternalMessageDialog(Desktop.desktop,
 
               MessageManager.getString("label.couldnt_create_groovy_shell"),
@@ -2640,8 +2705,11 @@ public class Desktop extends jalview.jbgui.GDesktop
   {
     if (groovyConsole == null)
     {
-      groovyConsole = new groovy.ui.Console();
-      groovyConsole.setVariable("Jalview", this);
+      JalviewObjectI j = new JalviewObject(this);
+      groovyConsole = new groovy.console.ui.Console();
+      groovyConsole.setVariable(JalviewObjectI.jalviewObjectName, j);
+      groovyConsole.setVariable(JalviewObjectI.currentAlFrameName,
+              getCurrentAlignFrame());
       groovyConsole.run();
 
       /*
@@ -2714,7 +2782,7 @@ public class Desktop extends jalview.jbgui.GDesktop
      */
     groovyShell.setEnabled(!enabled);
 
-    AlignFrame[] alignFrames = getAlignFrames();
+    AlignFrame[] alignFrames = getDesktopAlignFrames();
     if (alignFrames != null)
     {
       for (AlignFrame af : alignFrames)
@@ -3025,7 +3093,16 @@ public class Desktop extends jalview.jbgui.GDesktop
    */
   public static void showUrl(final String url)
   {
-    showUrl(url, Desktop.instance);
+    if (url != null && !url.trim().equals(""))
+    {
+      jalview.bin.Console.info("Opening URL: " + url);
+      showUrl(url, Desktop.instance);
+    }
+    else
+    {
+      jalview.bin.Console.warn("Ignoring attempt to show an empty URL.");
+    }
+
   }
 
   /**
@@ -3049,7 +3126,7 @@ public class Desktop extends jalview.jbgui.GDesktop
           {
             progress.setProgressBar(MessageManager
                     .formatMessage("status.opening_params", new Object[]
-                    { url }), this.hashCode());
+                    { url }), IdUtils.newId(IdType.PROGRESS, this));
           }
           jalview.util.BrowserLauncher.openURL(url);
         } catch (Exception ex)
@@ -3064,7 +3141,8 @@ public class Desktop extends jalview.jbgui.GDesktop
         }
         if (progress != null)
         {
-          progress.setProgressBar(null, this.hashCode());
+          progress.setProgressBar(null,
+                  IdUtils.newId(IdType.PROGRESS, this));
         }
       }
     }).start();
@@ -3123,7 +3201,7 @@ public class Desktop extends jalview.jbgui.GDesktop
    */
   private Semaphore block = new Semaphore(0);
 
-  private static groovy.ui.Console groovyConsole;
+  private static groovy.console.ui.Console groovyConsole;
 
   /**
    * add another dialog thread to the queue
@@ -3385,7 +3463,7 @@ public class Desktop extends jalview.jbgui.GDesktop
     myTopFrame.setDisplayedView(myTopFrame.alignPanel);
   }
 
-  public static groovy.ui.Console getGroovyConsole()
+  public static groovy.console.ui.Console getGroovyConsole()
   {
     return groovyConsole;
   }
@@ -3676,32 +3754,35 @@ public class Desktop extends jalview.jbgui.GDesktop
   }
 
   /**
-   * closes the current instance window, disposes and forgets about it.
+   * closes the current instance window, but leaves the JVM running. Bypasses
+   * any shutdown prompts, but does not set window dispose on close in case JVM
+   * terminates.
    */
   public static void closeDesktop()
   {
     if (Desktop.instance != null)
     {
-      Desktop.instance.closeAll_actionPerformed(null);
-      Desktop.instance.setVisible(false);
       Desktop us = Desktop.instance;
-      Desktop.instance = null;
+      Desktop.instance.quitTheDesktop(false, false);
       // call dispose in a separate thread - try to avoid indirect deadlocks
-      new Thread(new Runnable()
+      if (us != null)
       {
-        @Override
-        public void run()
+        new Thread(new Runnable()
         {
-          ExecutorService dex = us.dialogExecutor;
-          if (dex != null)
+          @Override
+          public void run()
           {
-            dex.shutdownNow();
-            us.dialogExecutor = null;
-            us.block.drainPermits();
+            ExecutorService dex = us.dialogExecutor;
+            if (dex != null)
+            {
+              dex.shutdownNow();
+              us.dialogExecutor = null;
+              us.block.drainPermits();
+            }
+            us.dispose();
           }
-          us.dispose();
-        }
-      }).start();
+        }).start();
+      }
     }
   }
 
@@ -3771,7 +3852,7 @@ public class Desktop extends jalview.jbgui.GDesktop
           boolean html, boolean modal, int timeout)
   {
     nonBlockingDialog(32, 2, title, message, boxtext, button, type,
-            scrollable, false, modal, timeout);
+            scrollable, html, modal, timeout);
   }
 
   public void nonBlockingDialog(int width, int height, String title,
@@ -3845,4 +3926,9 @@ public class Desktop extends jalview.jbgui.GDesktop
             { button }, button, modal, new JButton[] { jb }, false);
   }
 
+  @Override
+  public AlignFrame getCurrentAlignFrame()
+  {
+    return Jalview.getInstance().getCurrentAlignFrame();
+  }
 }