1 /* $RCSfile$
2  * $Author: hansonr $
3  * $Date: 2012-09-11 19:29:26 -0500 (Tue, 11 Sep 2012) $
4  * $Revision: 17556 $
5  *
6  * Copyright (C) 2004-2005  The Jmol Development Team
7  *
8  * Contact: jmol-developers@lists.sf.net
9  *
10  *  This library is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU Lesser General Public
12  *  License as published by the Free Software Foundation; either
13  *  version 2.1 of the License, or (at your option) any later version.
14  *
15  *  This library is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 package org.jmol.appletjs;
26 
27 import java.net.URL;
28 import java.util.Hashtable;
29 import java.util.Map;
30 
31 import javajs.api.JSInterface;
32 import javajs.util.PT;
33 
34 import org.jmol.api.js.JmolToJSmolInterface;
35 import org.jmol.util.GenericApplet;
36 import org.jmol.util.Logger;
37 import org.jmol.util.Parser;
38 
39 /**
40  * Java2Script rendition of Jmol using HTML5-only or WebGL-based graphics
41  *
42  * @author Bob Hanson hansonr@stolaf.edu, Takanori Nakane, with the assistance
43  *         of Jhou Renjian
44  *
45  */
46 
47 public class Jmol extends GenericApplet implements JSInterface {
48 
49   private Map<String, Object> htParams;
50 
51   /**
52    * cannot ignore super because it involves preparing fields
53    * @param vwrOptions
54    *
55    */
Jmol(Map<String, Object> vwrOptions)56   public Jmol(Map<String, Object> vwrOptions) {
57     htParams = new Hashtable<String, Object>();
58     if (vwrOptions == null)
59       vwrOptions = new Hashtable<String, Object>();
60     this.vwrOptions = vwrOptions;
61     for (Map.Entry<String, Object> entry : vwrOptions.entrySet())
62       htParams.put(entry.getKey().toLowerCase(), entry.getValue());
63     documentBase = "" + vwrOptions.get("documentBase");
64     codeBase = "" + vwrOptions.get("codePath");
65     isJS = true;
66     init(this);
67   }
68 
69   @Override
setStereoGraphics(boolean isStereo)70   public Object setStereoGraphics(boolean isStereo) {
71     /**
72      * @j2sNative
73      *
74      * if (isStereo)
75      *   return vwr.apiPlatform.context;
76      *
77      */
78     {
79     }
80     return null;
81   }
82 
83   @Override
initOptions()84   protected void initOptions() {
85     vwrOptions.remove("debug");
86     vwrOptions.put("fullName", fullName);
87     haveDocumentAccess = "true".equalsIgnoreCase(""
88         + getValue("allowjavascript", "true"));
89     mayScript = true;
90   }
91 
92   @Override
getJmolParameter(String paramName)93   protected String getJmolParameter(String paramName) {
94     Object o = htParams.get(paramName.toLowerCase());
95     return (o == null ? null : "" + o);
96   }
97 
98   @Override
doSendJsTextStatus(String message)99   protected void doSendJsTextStatus(String message) {
100     System.out.println(message);
101     // not implemented
102   }
103 
104   @Override
doSendJsTextareaStatus(String message)105   protected void doSendJsTextareaStatus(String message) {
106     System.out.println(message);
107     // not implemented
108   }
109 
110   @Override
doFunctionXY(String functionName, int nX, int nY)111   protected float[][] doFunctionXY(String functionName, int nX, int nY) {
112     /*three options:
113      *
114      *  nX > 0  and  nY > 0        return one at a time, with (slow) individual function calls
115      *  nX < 0  and  nY > 0        return a string that can be parsed to give the list of values
116      *  nX < 0  and  nY < 0        fill the supplied float[-nX][-nY] array directly in JavaScript
117      *
118      */
119 
120     //System.out.println("functionXY" + nX + " " + nY  + " " + functionName);
121     float[][] fxy = new float[Math.abs(nX)][Math.abs(nY)];
122     if (!mayScript || !haveDocumentAccess || nX == 0 || nY == 0)
123       return fxy;
124     try {
125       if (nX > 0 && nY > 0) { // fill with individual function calls (slow)
126         for (int i = 0; i < nX; i++)
127           for (int j = 0; j < nY; j++) {
128             /**
129              * @j2sNative
130              *
131              *            fxy[i][j] = window.eval(functionName)(this.htmlName, i, j);
132              */
133             {
134             }
135           }
136       } else if (nY > 0) { // fill with parsed values from a string (pretty fast)
137         String data;
138         /**
139          * @j2sNative
140          *
141          *            data = window.eval(functionName)(this.htmlName, nX, nY);
142          *
143          */
144         {
145           data = "";
146         }
147         nX = Math.abs(nX);
148         float[] fdata = new float[nX * nY];
149         Parser.parseStringInfestedFloatArray(data, null, fdata);
150         for (int i = 0, ipt = 0; i < nX; i++) {
151           for (int j = 0; j < nY; j++, ipt++) {
152             fxy[i][j] = fdata[ipt];
153           }
154         }
155       } else { // fill float[][] directly using JavaScript
156         /**
157          * @j2sNative
158          *
159          *            data = window.eval(functionName)(this.htmlName, nX, nY, fxy);
160          *
161          */
162         {
163           System.out.println(functionName);
164         }
165       }
166     } catch (Exception e) {
167       Logger.error("Exception " + e + " with nX, nY: " + nX + " " + nY);
168     }
169     // for (int i = 0; i < nX; i++)
170     // for (int j = 0; j < nY; j++)
171     //System.out.println("i j fxy " + i + " " + j + " " + fxy[i][j]);
172     return fxy;
173   }
174 
175   @Override
doFunctionXYZ(String functionName, int nX, int nY, int nZ)176   protected float[][][] doFunctionXYZ(String functionName, int nX, int nY,
177                                       int nZ) {
178     float[][][] fxyz = new float[Math.abs(nX)][Math.abs(nY)][Math.abs(nZ)];
179     if (!mayScript || !haveDocumentAccess || nX == 0 || nY == 0 || nZ == 0)
180       return fxyz;
181     try {
182       /**
183        * @j2sNative
184        *
185        *            window.eval(functionName)(this.htmlName, nX, nY, nZ, fxyz);
186        *
187        */
188       {
189       }
190     } catch (Exception e) {
191       Logger.error("Exception " + e + " for " + functionName
192           + " with nX, nY, nZ: " + nX + " " + nY + " " + nZ);
193     }
194     // for (int i = 0; i < nX; i++)
195     // for (int j = 0; j < nY; j++)
196     // for (int k = 0; k < nZ; k++)
197     //System.out.println("i j k fxyz " + i + " " + j + " " + k + " " + fxyz[i][j][k]);
198     return fxyz;
199   }
200 
201   @Override
doShowDocument(URL url)202   protected void doShowDocument(URL url) {
203     String[] surl = PT.split(url.toString(), "?POST?");
204     if (surl.length == 1) {
205       /**
206        * @j2sNative
207        *
208        *            window.open(surl[0]);
209        *
210        */
211     {}
212      return;
213       }
214 
215     String f = "<form id=f method=POST action='" + surl[0] + "'>";
216     f += "<input type='hidden' name='name' value='nmr-1h-prediction' id='name'>";
217     f += "<input type='submit' value='working...'>";
218     String[] fields = surl[1].split("&");
219     for (int i = 0; i < fields.length; i++) {
220       String field = fields[i];
221       int pt = field.indexOf("=");
222       String name = field.substring(0, pt);
223       String value = field.substring(pt);
224       if (value.indexOf("\n") >= 0) {
225         f +="<textarea style='display:none' name=" + name + ">" + value +"</textarea>";
226       } else {
227         f +="<input type=hidden name=" + name + " value=\""+ value +"\">";
228       }
229     }
230     f += "</form>";
231     /**
232      * @j2sNative
233      * var w=window.open("");w.document.write(f);w.document.getElementById("f").submit();
234      *
235      */
236     {
237       System.out.println(f + url);
238     }
239   }
240 
241   @Override
doSendCallback(String callback, Object[] data, String strInfo)242   protected String doSendCallback(String callback, Object[] data, String strInfo) {
243     if (callback == null || callback.length() == 0) {
244     } else if (callback.equals("alert")) {
245       /**
246        * @j2sNative alert(strInfo); return "";
247        */
248       {
249         System.out.println(strInfo);
250       }
251     } else {
252       String[] tokens = PT.split(callback, ".");
253       /**
254        * @j2sNative
255        *
256        *            try{
257        *            var o = window[tokens[0]];
258        *            for (var i = 1; i < tokens.length; i++)
259        *              o = o[tokens[i]];
260        *            for (var i = 0; i < data.length; i++)
261        *              data[i] && data[i].booleanValue && (data[i] = data[i].booleanValue());
262        *            return o.apply(null,data)
263        *            } catch (e) { System.out.println(callback + " failed " + e); }
264        */
265       {
266         System.out.println(tokens + " " + data);
267       }
268     }
269     return "";
270   }
271 
272   /**
273    * return RAW JAVASCRIPT OBJECT, NOT A STRING
274    */
275   @Override
doEval(String strEval)276   protected String doEval(String strEval) {
277     try {
278       /**
279        *
280        * @j2sNative
281        *
282        *            return window.eval(strEval);
283        */
284       {
285       }
286     } catch (Exception e) {
287       Logger.error("# error evaluating " + strEval + ":" + e.toString());
288     }
289     return "";
290   }
291 
292   @Override
doShowStatus(String message)293   protected void doShowStatus(String message) {
294     try {
295       System.out.println(message);
296     } catch (Exception e) {
297       //ignore if page is closing
298     }
299   }
300 
301   /**
302    * This method is only called by JmolGLmol applet._refresh();
303    *
304    * @return enough data to update a WebGL view
305    *
306    */
getGLmolView()307   public Object getGLmolView() {
308     return viewer.getGLmolView();
309   }
310 
311   /**
312    * possibly called from JSmolApplet.js upon start up
313    *
314    * @param fileName
315    * @return error or null
316    */
317 
openFile(String fileName)318   public String openFile(String fileName) {
319     return viewer.openFile(fileName);
320   }
321 
322   // JSInterface -- methods called from JSmol JavaScript library
323 
324   @Override
cacheFileByName(String fileName, boolean isAdd)325   public int cacheFileByName(String fileName, boolean isAdd) {
326     return viewer.cacheFileByName(fileName, isAdd);
327   }
328 
329   @Override
cachePut(String key, Object data)330   public void cachePut(String key, Object data) {
331     viewer.cachePut(key, data);
332   }
333 
334   @Override
getFullName()335   public String getFullName() {
336     return fullName;
337   }
338 
339   @Override
processMouseEvent(int id, int x, int y, int modifiers, long time)340   public boolean processMouseEvent(int id, int x, int y, int modifiers,
341                                    long time) {
342     return viewer.processMouseEvent(id, x, y, modifiers, time);
343   }
344 
345   @Override
setDisplay(Object canvas)346   public void setDisplay(Object canvas) {
347     viewer.setDisplay(canvas);
348   }
349 
350   @Override
setStatusDragDropped(int mode, int x, int y, String fileName)351   public boolean setStatusDragDropped(int mode, int x, int y, String fileName) {
352     return viewer.setStatusDragDropped(mode, x, y, fileName);
353   }
354 
355   @Override
startHoverWatcher(boolean enable)356   public void startHoverWatcher(boolean enable) {
357     viewer.startHoverWatcher(enable);
358   }
359 
360   @Override
update()361   public void update() {
362     viewer.updateJS();
363   }
364 
365   @Override
openFileAsyncSpecial(String fileName, int flags)366   public void openFileAsyncSpecial(String fileName, int flags) {
367     viewer.openFileAsyncSpecial(fileName, flags);
368   }
369 
370   @Override
processTwoPointGesture(float[][][] touches)371   public void processTwoPointGesture(float[][][] touches) {
372     viewer.processTwoPointGesture(touches);
373   }
374 
375   @Override
setScreenDimension(int width, int height)376   public void setScreenDimension(int width, int height) {
377     viewer.setScreenDimension(width, height);
378   }
379 
380   @Override
resizeInnerPanel(String data)381   public int[] resizeInnerPanel(String data) {
382     float[] dims = new float[2];
383     Parser.parseStringInfestedFloatArray(data, null, dims);
384     resizeDisplay((int) dims[0], (int) dims[1]);
385     return new int[] { (int) dims[0], (int) dims[1] };
386   }
387 
resizeDisplay(int width, int height)388   void resizeDisplay(int width, int height) {
389     JmolToJSmolInterface jmol = org.jmol.awtjs2d.Platform.Jmol();
390     jmol.resizeApplet(viewer.html5Applet, new int[] {width, height});
391   }
392 
393 }
394