JAL-1812 JAL-2068 only allow one Groovy console open at a time
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 25 Apr 2016 09:26:20 +0000 (10:26 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 25 Apr 2016 09:26:20 +0000 (10:26 +0100)
src/jalview/gui/Desktop.java

index 8e863c1..392bf32 100644 (file)
@@ -47,6 +47,7 @@ import java.awt.GridLayout;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.Toolkit;
+import java.awt.Window;
 import java.awt.datatransfer.Clipboard;
 import java.awt.datatransfer.ClipboardOwner;
 import java.awt.datatransfer.DataFlavor;
@@ -72,6 +73,8 @@ import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Hashtable;
@@ -2492,7 +2495,6 @@ public class Desktop extends jalview.jbgui.GDesktop implements
    */
   public void groovyShell_actionPerformed()
   {
-    // use reflection to avoid creating compilation dependency.
     if (!jalview.bin.Cache.groovyJarsPresent())
     {
       throw new Error(
@@ -2501,27 +2503,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     }
     try
     {
-      Class<?> gcClass = Desktop.class.getClassLoader().loadClass(
-              "groovy.ui.Console");
-      Constructor<?> gccons = gcClass.getConstructor();
-      java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
-              new Class[] { String.class, Object.class });
-      java.lang.reflect.Method run = gcClass.getMethod("run");
-      groovyConsole = gccons.newInstance();
-      setvar.invoke(groovyConsole, new Object[] { "Jalview", this });
-      run.invoke(groovyConsole);
-      /*
-       * and rebuild alignframe menus to enable 'Run Groovy'
-       */
-
-      AlignFrame[] alignFrames = getAlignFrames();
-      if (alignFrames != null)
-      {
-        for (AlignFrame af : alignFrames)
-        {
-          af.setGroovyEnabled(true);
-        }
-      }
+      openGroovyConsole();
     } catch (Exception ex)
     {
       jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
@@ -2534,6 +2516,81 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   }
 
   /**
+   * Open the Groovy console, using reflection to avoid creating compile-time
+   * dependency on Groovy libraries
+   * 
+   * @throws ClassNotFoundException
+   * @throws NoSuchMethodException
+   * @throws InstantiationException
+   * @throws IllegalAccessException
+   * @throws InvocationTargetException
+   */
+  void openGroovyConsole() throws ClassNotFoundException,
+          NoSuchMethodException, InstantiationException,
+          IllegalAccessException, InvocationTargetException
+  {
+    Class<?> gcClass = Desktop.class.getClassLoader().loadClass(
+            "groovy.ui.Console");
+    Constructor<?> gccons = gcClass.getConstructor();
+    groovyConsole = gccons.newInstance();
+
+    /*
+     * bind groovy variable 'Jalview' to the Desktop object
+     */
+    Method setvar = gcClass.getMethod("setVariable", new Class[] {
+        String.class, Object.class });
+    setvar.invoke(groovyConsole, new Object[] { "Jalview", this });
+
+    /*
+     * start the console
+     */
+    Method run = gcClass.getMethod("run");
+    run.invoke(groovyConsole);
+
+    /*
+     * Allow only one console at a time, so that the AlignFrame menu option
+     * 'Calculate | Run Groovy script' is unambiguous.
+     * Disable 'new console', and enable 'Run script', when the console is 
+     * opened, and the reverse when it is closed
+     */
+    Method getFrame = gcClass.getMethod("getFrame");
+    Window window = (Window) getFrame.invoke(groovyConsole);
+    window.addWindowListener(new WindowAdapter()
+    {
+      @Override
+      public void windowClosed(WindowEvent e)
+      {
+        groovyShell.setEnabled(true);
+        enableExecuteGroovy(false);
+      }
+    });
+
+    /*
+     * if we got this far, enable 'Run Groovy' in AlignFrame menus
+     * and disable opening a second console
+     */
+    groovyShell.setEnabled(false);
+    enableExecuteGroovy(true);
+  }
+
+  /**
+   * Enable or disable 'Run Groovy script' in AlignFrame calculate menus
+   * 
+   * @param enabled
+   */
+  public void enableExecuteGroovy(boolean enabled)
+  {
+    AlignFrame[] alignFrames = getAlignFrames();
+    if (alignFrames != null)
+    {
+      for (AlignFrame af : alignFrames)
+      {
+        af.setGroovyEnabled(enabled);
+      }
+    }
+  }
+
+  /**
    * Progress bars managed by the IProgressIndicator method.
    */
   private Hashtable<Long, JPanel> progressBars;