JAL-1812 JAL-2068 only allow one Groovy console open at a time
[jalview.git] / src / jalview / gui / Desktop.java
index 8ba21e5..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;
@@ -383,7 +386,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       @Override
       public void mousePressed(MouseEvent evt)
       {
-        if (SwingUtilities.isRightMouseButton(evt))
+        if (evt.isPopupTrigger())
         {
           showPasteMenu(evt.getX(), evt.getY());
         }
@@ -653,7 +656,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         String file = (String) contents
                 .getTransferData(DataFlavor.stringFlavor);
 
-        String format = new IdentifyFile().Identify(file,
+        String format = new IdentifyFile().identify(file,
                 FormatAdapter.PASTE);
 
         new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
@@ -1007,7 +1010,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
           }
           else
           {
-            format = new IdentifyFile().Identify(file, protocol);
+            format = new IdentifyFile().identify(file, protocol);
           }
 
           new FileLoader().LoadFile(file, protocol, format);
@@ -1058,20 +1061,13 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       }
       else
       {
-        format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
+        format = new IdentifyFile().identify(choice, FormatAdapter.FILE);
       }
 
       if (viewport != null)
       {
         new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
                 format);
-        // viewport.setShowSequenceFeatures(JSONFile.isSeqFeaturesEnabled());
-        // AlignFrame af = viewport.getAlignPanel().alignFrame;
-        // if (af != null)
-        // {
-        // af.changeColour(JSONFile.getColourScheme());
-        // af.setMenusForViewport();
-        // }
       }
       else
       {
@@ -1141,7 +1137,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     }
     else
     {
-      String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
+      String format = new IdentifyFile().identify(url, FormatAdapter.URL);
 
       if (format.equals("URL NOT FOUND"))
       {
@@ -2499,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(
@@ -2508,15 +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");
-      Object gc = gccons.newInstance();
-      setvar.invoke(gc, new Object[] { "Jalview", this });
-      run.invoke(gc);
+      openGroovyConsole();
     } catch (Exception ex)
     {
       jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
@@ -2529,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;
@@ -2924,6 +2986,13 @@ public class Desktop extends jalview.jbgui.GDesktop implements
    */
   private java.util.concurrent.Semaphore block = new Semaphore(0);
 
+  /*
+   * groovy.ui.Console object - if Groovy jars are present and the 
+   * user has activated the Groovy console. Use via reflection to
+   * avoid compile-time dependency on Groovy libraries.
+   */
+  private static Object groovyConsole;
+
   /**
    * add another dialog thread to the queue
    * 
@@ -3152,4 +3221,9 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     Desktop.currentAlignFrame = currentAlignFrame;
   }
 
+  public static Object getGroovyConsole()
+  {
+    return groovyConsole;
+  }
+
 }