refactored javascript callback to parent class.
authorjprocter <Jim Procter>
Mon, 17 Jan 2011 13:59:00 +0000 (13:59 +0000)
committerjprocter <Jim Procter>
Mon, 17 Jan 2011 13:59:00 +0000 (13:59 +0000)
src/jalview/javascript/JSFunctionExec.java [new file with mode: 0644]
src/jalview/javascript/JsSelectionSender.java
src/jalview/javascript/MouseOverListener.java

diff --git a/src/jalview/javascript/JSFunctionExec.java b/src/jalview/javascript/JSFunctionExec.java
new file mode 100644 (file)
index 0000000..9674926
--- /dev/null
@@ -0,0 +1,217 @@
+package jalview.javascript;
+
+import java.net.URL;
+import java.util.Vector;
+
+import netscape.javascript.JSException;
+import netscape.javascript.JSObject;
+import jalview.bin.JalviewLite;
+
+public class JSFunctionExec implements Runnable
+{
+  JalviewLite jvlite;
+
+  public JSFunctionExec(JalviewLite applet)
+  {
+    jvlite = applet;
+  }
+
+  private static Vector jsExecQueue;
+
+  private static Thread executor = null;
+
+  public static void stopQueue()
+  {
+    if (jsExecQueue != null)
+    {
+      Vector q = jsExecQueue;
+      jsExecQueue = null;
+      q.removeAllElements();
+      executor.notify();
+      executor = null;
+    }
+  }
+
+  public void run()
+  {
+    while (jsExecQueue != null)
+    {
+      if (jsExecQueue.size() > 0)
+      {
+        Runnable r = (Runnable) jsExecQueue.elementAt(0);
+        jsExecQueue.removeElementAt(0);
+        try
+        {
+          r.run();
+        } catch (Exception ex)
+        {
+          ex.printStackTrace();
+        } catch (Error ex)
+        {
+          ex.printStackTrace();
+        }
+      }
+      else
+      {
+        try
+        {
+          synchronized (jsExecQueue)
+          {
+            jsExecQueue.wait(1000);
+          }
+        } catch (Exception ex)
+        {
+        }
+        ;
+      }
+    }
+
+  }
+
+  /**
+   * execute a javascript callback asynchronously
+   * 
+   * @param _listener
+   * @param objects
+   * @throws Exception
+   */
+  public void executeJavascriptFunction(final String _listener,
+          final Object[] objects) throws Exception
+  {
+    executeJavascriptFunction(false, _listener, objects);
+  }
+
+  /**
+   * execute a javascript callback synchronously or asynchronously
+   * 
+   * @param async
+   *          - true to execute asynchronously (do this for gui events)
+   * @param _listener
+   *          - javascript function
+   * @param objects
+   *          - arguments
+   * @throws Exception
+   *           - only if call is synchronous
+   */
+  public void executeJavascriptFunction(final boolean async,
+          final String _listener, Object[] arguments) throws Exception
+  {
+    final Object[] objects = new Object[arguments != null ? arguments.length
+            : 0];
+    if (arguments != null)
+    {
+      System.arraycopy(arguments, 0, objects, 0, arguments.length);
+    }
+    final Exception[] jsex = new Exception[1];
+    Runnable exec = new Runnable()
+    {
+      public void run()
+      {
+        try
+        {
+          JSObject scriptObject = null;
+          try
+          {
+            scriptObject = JSObject.getWindow(jvlite.applet);
+          } catch (Exception ex)
+          {
+          }
+          ;
+          if (scriptObject != null)
+          {
+            scriptObject.call(_listener, objects);
+          }
+        } catch (Exception jex)
+        {
+          // squash any malformedURLExceptions thrown by windows/safari
+          if (!(jex instanceof java.net.MalformedURLException))
+          {
+            if (jvlite.debug)
+            {
+              System.err.println(jex);
+            }
+            if (jex instanceof netscape.javascript.JSException)
+            {
+              jsex[0] = (netscape.javascript.JSException) jex;
+              if (jvlite.debug)
+              {
+                System.err.println("Falling back to javascript: url call");
+              }
+              StringBuffer sb = new StringBuffer("javascript:" + _listener
+                      + "(");
+              for (int i = 0; objects != null && i < objects.length; i++)
+              {
+                if (i > 0)
+                {
+                  sb.append(",");
+                }
+                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))
+                {
+                  sb.append(objects[i].toString());
+                }
+                sb.append("\"");
+              }
+              sb.append(")");
+              if (jvlite.debug)
+              {
+                System.err.println(sb.toString());
+              }
+              // alternate
+              URL url = null;
+              try
+              {
+                url = new URL(sb.toString());
+                jvlite.getAppletContext().showDocument(url);
+                jex = null;
+              } catch (Exception uex)
+              {
+                jex = uex;
+              }
+            }
+            if (jex != null)
+            {
+              if (async)
+              {
+                jex.printStackTrace();
+              }
+              else
+              {
+                jsex[0] = new Exception(jex);
+              }
+            }
+            ;
+          }
+
+        }
+      }
+    };
+    if (async)
+    {
+      if (JSFunctionExec.executor == null)
+      {
+        JSFunctionExec.jsExecQueue = new Vector();
+        JSFunctionExec.executor = new Thread(new JSFunctionExec(jvlite));
+        executor.start();
+      }
+      synchronized (jsExecQueue)
+      {
+        jsExecQueue.addElement(exec);
+        jsExecQueue.notify();
+      }
+    }
+    else
+    {
+      exec.run();
+      if (jsex[0] != null)
+      {
+        throw (jsex[0]);
+      }
+    }
+  }
+
+}
index 8b2ba2c..d948363 100644 (file)
@@ -1,8 +1,6 @@
 package jalview.javascript;
 
-import java.util.ArrayList;
-import java.util.Enumeration;
-
+import java.net.URL;
 import jalview.appletgui.AlignFrame;
 import jalview.appletgui.AlignViewport;
 import jalview.bin.JalviewLite;
@@ -11,10 +9,9 @@ import jalview.datamodel.SequenceGroup;
 import jalview.structure.SelectionSource;
 import netscape.javascript.JSObject;
 
-public class JsSelectionSender implements
+public class JsSelectionSender extends JSFunctionExec implements
         jalview.structure.SelectionListener, JsCallBack
 {
-  JalviewLite jvlite;
 
   AlignFrame _af;
 
@@ -23,7 +20,7 @@ public class JsSelectionSender implements
   public JsSelectionSender(JalviewLite jvlite, AlignFrame af,
           String listener)
   {
-    this.jvlite = jvlite;
+    super(jvlite);
     _af = af;
     _listener = listener;
   }
@@ -52,6 +49,8 @@ public class JsSelectionSender implements
                         .getSequenceSetId());
         for (int a = 0; a < aps.length; a++)
         {
+          System.out.println("Selection: testing source alignPanel : "
+                  + aps[a].getName());
           if (aps[a].av == source)
           {
             src = aps[a].alignFrame;
@@ -64,12 +63,12 @@ public class JsSelectionSender implements
         System.err.println("Unhandled selection source !");
         return;
       }
-      JSObject jsoWindow = JSObject.getWindow(jvlite);
       String[] seqs = new String[]
       {};
       String[] cols = new String[]
       {};
-      int strt = 0, end = src.alignPanel.av.getAlignment().getWidth();
+      int strt = 0, end = (src == null) ? -1 : src.alignPanel.av
+              .getAlignment().getWidth();
       if (seqsel != null && seqsel.getSize() > 0)
       {
         seqs = new String[seqsel.getSize()];
@@ -81,18 +80,24 @@ public class JsSelectionSender implements
         {
           strt = seqsel.getStartRes();
         }
-        if (end > seqsel.getEndRes())
+        if (end==-1 || end > seqsel.getEndRes())
         {
           end = seqsel.getEndRes();
         }
       }
       if (colsel != null && colsel.size() > 0)
       {
+        if (end == -1)
+        {
+          end = colsel.getMax() + 1;
+        }
         cols = new String[colsel.getSelected().size()];
         int d = 0, r = -1;
         for (int i = 0; i < cols.length; i++)
         {
-          cols[i] = ""+(1+((Integer)colsel.getSelected().elementAt(i)).intValue());
+          cols[i] = ""
+                  + (1 + ((Integer) colsel.getSelected().elementAt(i))
+                          .intValue());
         }
       }
       else
@@ -107,26 +112,27 @@ public class JsSelectionSender implements
 
       }
       System.err.println("Relaying selection to jsfunction:" + _listener);
-      jsoWindow.call(
-              _listener,
-              new Object[]
-              { src, setid, jvlite.arrayToSeparatorList(seqs),
-                  jvlite.arrayToSeparatorList(cols) });
+      executeJavascriptFunction( _listener,
+                new Object[]
+                { src, setid, jvlite.arrayToSeparatorList(seqs),
+                    jvlite.arrayToSeparatorList(cols) });
     } catch (Exception ex)
     {
       System.err
               .println("Jalview Javascript exec error: Couldn't send selection message using function '"
                       + _listener + "'");
+      ex.printStackTrace();
       if (ex instanceof netscape.javascript.JSException)
       {
-        System.err.println("Javascript Exception: "+((netscape.javascript.JSException)ex).getMessage());
+        System.err.println("Javascript Exception: "
+                + ((netscape.javascript.JSException) ex).getCause()
+                        .toString());
       }
-      else {
-        ex.printStackTrace();
-      };
+
     }
   }
 
+
   @Override
   public AlignFrame getAlignFrame()
   {
index 462092e..c2ae6ef 100644 (file)
@@ -6,9 +6,8 @@ import jalview.datamodel.SequenceI;
 import jalview.structure.VamsasListener;
 import netscape.javascript.JSObject;
 
-public class MouseOverListener implements VamsasListener,JsCallBack
+public class MouseOverListener extends JSFunctionExec implements VamsasListener,JsCallBack
 {
-  JalviewLite jvlite;
   AlignFrame _af;
   String _listener;
   SequenceI last = null;
@@ -25,8 +24,7 @@ public class MouseOverListener implements VamsasListener,JsCallBack
         last = seq;
         i = index;
         try {
-        JSObject js = JSObject.getWindow(jvlite);
-        js.call(_listener, new Object[] { _af, seq.getDisplayId(false), ""+(1+i)});
+        executeJavascriptFunction(_listener, new Object[] { _af, seq.getDisplayId(false), ""+(1+i)});
         } catch (Exception ex)
         {
           
@@ -35,16 +33,14 @@ public class MouseOverListener implements VamsasListener,JsCallBack
           {
             System.err.println("Javascript Exception: "+((netscape.javascript.JSException)ex).getMessage());
           }
-          else {
-            ex.printStackTrace();
-          };
+          ex.printStackTrace();
       }
     }
   }
   
   public MouseOverListener(JalviewLite applet, AlignFrame af, String listener)
   {
-    this.jvlite = applet;
+    super(applet);
     _af = af;
     _listener = listener;
   }