JAL-3210 Improvements to eclipse detection. New src tree and SwingJS updated from...
[jalview.git] / src / jalview / javascript / JSFunctionExec.java
index 9674926..ad7a379 100644 (file)
@@ -1,44 +1,86 @@
+/*
+ * 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 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.javascript;
 
+import jalview.api.JalviewApp;
+
 import java.net.URL;
+import java.util.Hashtable;
 import java.util.Vector;
 
-import netscape.javascript.JSException;
 import netscape.javascript.JSObject;
-import jalview.bin.JalviewLite;
 
 public class JSFunctionExec implements Runnable
 {
-  JalviewLite jvlite;
+  public JalviewApp jvlite;
+
+  protected boolean debug;
 
-  public JSFunctionExec(JalviewLite applet)
+  public JSFunctionExec(JalviewApp applet, boolean debug)
   {
     jvlite = applet;
+    this.debug = debug;
+    jsExecQueue = jvlite.getJsExecQueue(this);
   }
 
-  private static Vector jsExecQueue;
+  private Vector<Runnable> jsExecQueue;
 
-  private static Thread executor = null;
+  private Thread executor = null;
 
-  public static void stopQueue()
+  public void stopQueue()
   {
     if (jsExecQueue != null)
     {
-      Vector q = jsExecQueue;
-      jsExecQueue = null;
-      q.removeAllElements();
-      executor.notify();
-      executor = null;
+      Vector<Runnable> q = null;
+      synchronized (jsExecQueue)
+      {
+        q = jsExecQueue;
+        jsExecQueue = null;
+      }
+      if (q != null)
+      {
+        for (Runnable jx : q)
+        {
+          ((JSFunctionExec) jx).jvlite = null;
+
+        }
+        q.removeAllElements();
+        synchronized (q)
+        {
+          q.notifyAll();
+        }
+      }
     }
+    jvlite = null;
+    executor = null;
   }
 
+  @Override
   public void run()
   {
     while (jsExecQueue != null)
     {
       if (jsExecQueue.size() > 0)
       {
-        Runnable r = (Runnable) jsExecQueue.elementAt(0);
+        Runnable r = jsExecQueue.elementAt(0);
         jsExecQueue.removeElementAt(0);
         try
         {
@@ -69,7 +111,7 @@ public class JSFunctionExec implements Runnable
   }
 
   /**
-   * execute a javascript callback asynchronously
+   * execute a javascript callback synchronously
    * 
    * @param _listener
    * @param objects
@@ -96,6 +138,15 @@ public class JSFunctionExec implements Runnable
   public void executeJavascriptFunction(final boolean async,
           final String _listener, Object[] arguments) throws Exception
   {
+
+    executeJavascriptFunction(async, _listener, arguments, null);
+
+  }
+
+  public void executeJavascriptFunction(final boolean async,
+          final String _listener, Object[] arguments, final String dbgMsg)
+          throws Exception
+  {
     final Object[] objects = new Object[arguments != null ? arguments.length
             : 0];
     if (arguments != null)
@@ -105,6 +156,7 @@ public class JSFunctionExec implements Runnable
     final Exception[] jsex = new Exception[1];
     Runnable exec = new Runnable()
     {
+      @Override
       public void run()
       {
         try
@@ -112,13 +164,17 @@ public class JSFunctionExec implements Runnable
           JSObject scriptObject = null;
           try
           {
-            scriptObject = JSObject.getWindow(jvlite.applet);
+            scriptObject = jvlite.getJSObject();
           } catch (Exception ex)
           {
           }
           ;
           if (scriptObject != null)
           {
+            if (debug && dbgMsg != null)
+            {
+              System.err.println(dbgMsg);
+            }
             scriptObject.call(_listener, objects);
           }
         } catch (Exception jex)
@@ -126,19 +182,20 @@ public class JSFunctionExec implements Runnable
           // squash any malformedURLExceptions thrown by windows/safari
           if (!(jex instanceof java.net.MalformedURLException))
           {
-            if (jvlite.debug)
+            if (debug)
             {
               System.err.println(jex);
             }
-            if (jex instanceof netscape.javascript.JSException)
+            if (jex instanceof netscape.javascript.JSException
+                    && jvlite.isJsfallbackEnabled())
             {
-              jsex[0] = (netscape.javascript.JSException) jex;
-              if (jvlite.debug)
+              jsex[0] = jex;
+              if (debug)
               {
                 System.err.println("Falling back to javascript: url call");
               }
-              StringBuffer sb = new StringBuffer("javascript:" + _listener
-                      + "(");
+              StringBuffer sb = new StringBuffer(
+                      "javascript:" + _listener + "(");
               for (int i = 0; objects != null && i < objects.length; i++)
               {
                 if (i > 0)
@@ -148,16 +205,15 @@ public class JSFunctionExec implements Runnable
                 sb.append("\"");
                 // strip out nulls and complex objects that we can't pass this
                 // way.
-                if (objects[i] != null
-                        && !(objects[i].getClass().getPackage().getName()
-                                .indexOf("jalview") == 0))
+                if (objects[i] != null && !(objects[i].getClass().getName()
+                        .indexOf("jalview") == 0))
                 {
                   sb.append(objects[i].toString());
                 }
                 sb.append("\"");
               }
               sb.append(")");
-              if (jvlite.debug)
+              if (debug)
               {
                 System.err.println(sb.toString());
               }
@@ -181,7 +237,7 @@ public class JSFunctionExec implements Runnable
               }
               else
               {
-                jsex[0] = new Exception(jex);
+                jsex[0] = jex;
               }
             }
             ;
@@ -192,10 +248,9 @@ public class JSFunctionExec implements Runnable
     };
     if (async)
     {
-      if (JSFunctionExec.executor == null)
+      if (executor == null)
       {
-        JSFunctionExec.jsExecQueue = new Vector();
-        JSFunctionExec.executor = new Thread(new JSFunctionExec(jvlite));
+        executor = new Thread(new JSFunctionExec(jvlite, debug));
         executor.start();
       }
       synchronized (jsExecQueue)
@@ -206,6 +261,7 @@ public class JSFunctionExec implements Runnable
     }
     else
     {
+      // wat for executor to notify us if it's running.
       exec.run();
       if (jsex[0] != null)
       {
@@ -214,4 +270,80 @@ public class JSFunctionExec implements Runnable
     }
   }
 
+  public static void setJsMessageSet(String messageclass, String viewId,
+          String[] colcommands, JalviewApp app)
+  {
+    Hashtable<String, Hashtable<String, String[]>> jsmessages = app
+            .getJSMessages();
+    Hashtable<String, int[]> jshashes = app.getJSHashes();
+
+    Hashtable<String, String[]> msgset = jsmessages.get(messageclass);
+    if (msgset == null)
+    {
+      msgset = new Hashtable<>();
+      jsmessages.put(messageclass, msgset);
+    }
+    msgset.put(viewId, colcommands);
+    int[] l = new int[colcommands.length];
+    for (int i = 0; i < colcommands.length; i++)
+    {
+      l[i] = colcommands[i].hashCode();
+    }
+    jshashes.put(messageclass + "|" + viewId, l);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see jalview.bin.JalviewLiteJsApi#getJsMessage(java.lang.String,
+   * java.lang.String)
+   */
+  public static String getJsMessage(String messageclass, String viewId,
+          JalviewApp app)
+  {
+    Hashtable<String, String[]> msgset = app.getJSMessages()
+            .get(messageclass);
+    if (msgset != null)
+    {
+      String[] msgs = msgset.get(viewId);
+      if (msgs != null)
+      {
+        for (int i = 0; i < msgs.length; i++)
+        {
+          if (msgs[i] != null)
+          {
+            String m = msgs[i];
+            msgs[i] = null;
+            return m;
+          }
+        }
+      }
+    }
+    return "";
+  }
+
+  public static boolean isJsMessageSetChanged(String string, String string2,
+          String[] colcommands, JalviewApp app)
+  {
+    int[] l = app.getJSHashes().get(string + "|" + string2);
+    if (l == null && colcommands != null)
+    {
+      return true;
+    }
+    for (int i = 0; i < colcommands.length; i++)
+    {
+      if (l[i] != colcommands[i].hashCode())
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public void tidyUp()
+  {
+    stopQueue();
+    jvlite = null;
+  }
+
 }