1 package jspecview.js2d;
2 
3 import java.io.BufferedInputStream;
4 import java.net.URL;
5 import java.util.Map;
6 
7 import javax.swing.JOptionPane;
8 
9 import org.jmol.api.GenericFileInterface;
10 import org.jmol.api.GenericImageDialog;
11 import org.jmol.api.GenericMenuInterface;
12 import org.jmol.api.GenericMouseInterface;
13 import org.jmol.api.GenericPlatform;
14 import org.jmol.api.JmolInChI;
15 import org.jmol.api.PlatformViewer;
16 
17 import org.jmol.util.Font;
18 
19 import javajs.util.P3;
20 import javajs.util.AjaxURLStreamHandlerFactory;
21 import javajs.util.Rdr;
22 import javajs.util.SB;
23 
24 import jspecview.api.JSVPanel;
25 import jspecview.app.GenericMouse;
26 
27 
28 
29 /**
30  * JavaScript 2D canvas version requires Ajax-based URL stream processing.
31  *
32  * Jmol "display" --> HTML5 "canvas"
33  * Jmol "image" --> HTML5 "canvas" (because we need width and height)
34  * Jmol "graphics" --> HTML5 "context(2d)" (one for display, one off-screen for fonts)
35  * Jmol "font" --> JmolFont
36  * Jmol "fontMetrics" --> HTML5 "context(2d)"
37  * (Not fully implemented)
38  *
39  * @author Bob Hanson
40  *
41  */
42 public class JsPlatform implements GenericPlatform {
43   Object canvas;
44   PlatformViewer viewer;
45   Object context;
46 
47 	@Override
setViewer(PlatformViewer viewer, Object canvas)48 	public void setViewer(PlatformViewer viewer, Object canvas) {
49 		Object context = "";
50 		this.viewer = viewer;
51 		this.canvas = canvas;
52 	  /**
53 	   * @j2sNative
54 	   *
55      *     if (canvas != null) {
56 	   *       context = canvas.getContext("2d");
57 	   *       canvas.imgdata = context.getImageData(0, 0, canvas.width, canvas.height);
58 	   *       canvas.buf8 = canvas.imgdata.data;
59 	   *     }
60 	   */
61 	  {}
62 	  if (context != "")
63 	  	this.context = context;
64 		//
65 		try {
66 		  URL.setURLStreamHandlerFactory(new AjaxURLStreamHandlerFactory());
67 		} catch (Throwable e) {
68 		  // that's fine -- already created
69 		}
70 	}
71 
72   @Override
isSingleThreaded()73 	public boolean isSingleThreaded() {
74     return true;
75   }
76 
77   @Override
getJsObjectInfo(Object[] jsObject, String method, Object[] args)78 	public Object getJsObjectInfo(Object[] jsObject, String method, Object[] args) {
79     /**
80      * we must use Object[] here to hide [HTMLUnknownElement] and [Attribute] from Java2Script
81      * @j2sNative
82      *
83      * return (method == null ? null : method == "localName" ? jsObject[0]["nodeName"] : args == null ? jsObject[0][method] : jsObject[0][method](args[0]));
84      *
85      *
86      */
87     {
88       return null;
89     }
90   }
91 
92   @Override
isHeadless()93 	public boolean isHeadless() {
94     return false;
95   }
96 
97   @Override
getMouseManager(double privateKey, Object jsvp)98 	public GenericMouseInterface getMouseManager(double privateKey, Object jsvp) {
99   	return new GenericMouse((JSVPanel) jsvp);
100   }
101 
102   // /// Display
103 
104 	@Override
convertPointFromScreen(Object canvas, P3 ptTemp)105 	public void convertPointFromScreen(Object canvas, P3 ptTemp) {
106 	  // from JmolMultiTouchClientAdapter.fixXY
107 		Display.convertPointFromScreen(canvas, ptTemp);
108 	}
109 
110 	@Override
getFullScreenDimensions(Object canvas, int[] widthHeight)111 	public void getFullScreenDimensions(Object canvas, int[] widthHeight) {
112 		Display.getFullScreenDimensions(canvas, widthHeight);
113 	}
114 
115   @Override
getMenuPopup(String menuStructure, char type)116 	public GenericMenuInterface getMenuPopup(String menuStructure,
117                                          char type) {
118   	return null;
119   }
120 
121 	@Override
hasFocus(Object canvas)122 	public boolean hasFocus(Object canvas) {
123 		return Display.hasFocus(canvas);
124 	}
125 
126 	@Override
prompt(String label, String data, String[] list, boolean asButtons)127 	public String prompt(String label, String data, String[] list,
128 			boolean asButtons) {
129 		return Display.prompt(label, data, list, asButtons);
130 	}
131 
132 	/**
133 	 * legacy apps will use this
134 	 *
135 	 * @param context
136 	 * @param size
137 	 */
138 	@Override
renderScreenImage(Object context, Object size)139 	public void renderScreenImage(Object context, Object size) {
140 		Display.renderScreenImage(viewer, context, size);
141 	}
142 
143   @Override
drawImage(Object context, Object canvas, int x, int y, int width, int height, boolean isDTI)144 	public void drawImage(Object context, Object canvas, int x, int y, int width,
145                         int height, boolean isDTI) {
146 
147     // from Viewer.render1
148     Image.drawImage(context, canvas, x, y, width, height);
149   }
150 
151 	@Override
requestFocusInWindow(Object canvas)152 	public void requestFocusInWindow(Object canvas) {
153 		Display.requestFocusInWindow(canvas);
154 	}
155 
156 	@Override
repaint(Object canvas)157 	public void repaint(Object canvas) {
158 		Display.repaint(canvas);
159 	}
160 
161 	@Override
setTransparentCursor(Object canvas)162 	public void setTransparentCursor(Object canvas) {
163 		Display.setTransparentCursor(canvas);
164 	}
165 
166 	@Override
setCursor(int c, Object canvas)167 	public void setCursor(int c, Object canvas) {
168 		Display.setCursor(c, canvas);
169 	}
170 
171 	// //// Image
172 
173 	@Override
allocateRgbImage(int windowWidth, int windowHeight, int[] pBuffer, int windowSize, boolean backgroundTransparent, boolean isImageWrite)174 	public Object allocateRgbImage(int windowWidth, int windowHeight,
175 			int[] pBuffer, int windowSize, boolean backgroundTransparent, boolean isImageWrite) {
176 		return Image.allocateRgbImage(windowWidth, windowHeight, pBuffer,
177 				windowSize, backgroundTransparent, (isImageWrite ? null : canvas));
178 	}
179 
180   @Override
notifyEndOfRendering()181 	public void notifyEndOfRendering() {
182   }
183 
184   /**
185    * could be byte[] (from ZIP file) or String (local file name) or URL
186    * @param data
187    * @return image object
188    *
189    */
190 	@Override
createImage(Object data)191 	public Object createImage(Object data) {
192 	  // N/A in JS
193 	  return null;
194 	}
195 
196 	@Override
disposeGraphics(Object gOffscreen)197 	public void disposeGraphics(Object gOffscreen) {
198 	  // N/A
199 	}
200 
201 	@Override
grabPixels(Object canvas, int width, int height, int[] pixels, int startRow, int nRows)202 	public int[] grabPixels(Object canvas, int width, int height,
203                           int[] pixels, int startRow, int nRows) {
204 	  // from PNG and JPG image creators, also g3d.ImageRenderer.plotImage via drawImageToBuffer
205 
206 	  /**
207 	   *
208 	   * (might be just an object with buf32 defined -- WRITE IMAGE)
209 	   *
210 	   * @j2sNative
211 	   *
212 	   *     if (canvas.image && (width != canvas.width || height != canvas.height))
213      *       Jmol._setCanvasImage(canvas, width, height);
214 	   *     if (canvas.buf32) return canvas.buf32;
215 	   */
216 	  {}
217     int[] buf = Image.grabPixels(Image.getGraphics(canvas), width, height);
218     /**
219      * @j2sNative
220      *
221      *  canvas.buf32 = buf;
222      *
223      */
224     {}
225     return buf;
226 	}
227 
228 	@Override
drawImageToBuffer(Object gOffscreen, Object imageOffscreen, Object canvas, int width, int height, int bgcolor)229 	public int[] drawImageToBuffer(Object gOffscreen, Object imageOffscreen,
230 			Object canvas, int width, int height, int bgcolor) {
231 	  return grabPixels(canvas, width, height, null, 0, 0);
232 	}
233 
234 	@Override
getTextPixels(String text, Font font3d, Object context, Object image, int width, int height, int ascent)235 	public int[] getTextPixels(String text, Font font3d, Object context,
236 			Object image, int width, int height, int ascent) {
237 		return Image.getTextPixels(text, font3d, context, width, height, ascent);
238 	}
239 
240 	@Override
flushImage(Object imagePixelBuffer)241 	public void flushImage(Object imagePixelBuffer) {
242 	  // N/A
243 	}
244 
245 	@Override
getGraphics(Object canvas)246 	public Object getGraphics(Object canvas) {
247 		return (canvas == null ? context : (context = Image.getGraphics(this.canvas = canvas)));
248 	}
249 
250   @Override
getImageHeight(Object canvas)251 	public int getImageHeight(Object canvas) {
252 		return (canvas == null ? -1 : Image.getHeight(canvas));
253 	}
254 
255 	@Override
getImageWidth(Object canvas)256 	public int getImageWidth(Object canvas) {
257 		return (canvas == null ? -1 : Image.getWidth(canvas));
258 	}
259 
260 	@Override
getStaticGraphics(Object image, boolean backgroundTransparent)261 	public Object getStaticGraphics(Object image, boolean backgroundTransparent) {
262 		return Image.getStaticGraphics(image, backgroundTransparent);
263 	}
264 
265 	@Override
newBufferedImage(Object image, int w, int h)266 	public Object newBufferedImage(Object image, int w, int h) {
267     /**
268      * @j2sNative
269      *
270      *  if (self.Jmol && Jmol._getHiddenCanvas)
271      *    return Jmol._getHiddenCanvas(this.vwr.html5Applet, "stereoImage", w, h);
272      */
273     {}
274     return null;
275 	}
276 
277 	@Override
newOffScreenImage(int w, int h)278 	public Object newOffScreenImage(int w, int h) {
279     /**
280      * @j2sNative
281      *
282      *  if (self.Jmol && Jmol._getHiddenCanvas)
283      *    return Jmol._getHiddenCanvas(this.vwr.html5Applet, "textImage", w, h);
284      */
285     {}
286     return null;
287 	}
288 
289 	@Override
waitForDisplay(Object echoNameAndPath, Object zipBytes)290 	public boolean waitForDisplay(Object echoNameAndPath, Object zipBytes)
291 			throws InterruptedException {
292 		// not implmented in JSpecView
293 	  return false;
294 	}
295 
296 	// /// FONT
297 
298 	@Override
fontStringWidth(Font font, String text)299 	public int fontStringWidth(Font font, String text) {
300 		return JsFont.stringWidth(font, text);
301 	}
302 
303 	@Override
getFontAscent(Object context)304 	public int getFontAscent(Object context) {
305 		return JsFont.getAscent(context);
306 	}
307 
308 	@Override
getFontDescent(Object context)309 	public int getFontDescent(Object context) {
310 		return JsFont.getDescent(context);
311 	}
312 
313 	@Override
getFontMetrics(Font font, Object context)314 	public Object getFontMetrics(Font font, Object context) {
315 		return JsFont.getFontMetrics(font, context);
316 	}
317 
318 	@Override
newFont(String fontFace, boolean isBold, boolean isItalic, float fontSize)319 	public Object newFont(String fontFace, boolean isBold, boolean isItalic,
320 			float fontSize) {
321 		return JsFont.newFont(fontFace, isBold, isItalic, fontSize, "px");
322 	}
323 
324   @Override
getDateFormat(String isoType)325   public String getDateFormat(String isoType) {
326     /**
327      *
328      * Mon Jan 07 2013 19:54:39 GMT-0600 (Central Standard Time)
329      * or YYYYMMDDHHmmssOHH'mm'
330      *
331      * @j2sNative
332      *
333      * if (isoType == null) {
334      * } else if (isoType.indexOf("8824") >= 0) {
335      *   var d = new Date();
336      *   var x = d.toString().split(" ");
337      *   var MM = "0" + d.getMonth(); MM = MM.substring(MM.length - 2);
338      *   var dd = "0" + d.getDate(); dd = dd.substring(dd.length - 2);
339      *   return x[3] + MM + dd + x[4].replace(/\:/g,"") + x[5].substring(3,6) + "'" + x[5].substring(6,8) + "'"
340      * } else if (isoType.indexOf("8601") >= 0){
341      *   var d = new Date();
342      *   var x = d.toString().split(" ");
343      *   var MM = "0" + d.getMonth(); MM = MM.substring(MM.length - 2);
344      *   var dd = "0" + d.getDate(); dd = dd.substring(dd.length - 2);
345      *   return x[3] + MM + dd + x[4].replace(/\:/g,"") + x[5].substring(3,6) + "'" + x[5].substring(6,8) + "'"
346      * }
347      * return ("" + (new Date())).split(" (")[0];
348      */
349     {
350       return null;
351     }
352   }
353 
354   @Override
newFile(String name)355 	public GenericFileInterface newFile(String name) {
356     return new JsFile(name);
357   }
358 
359   @Override
getBufferedFileInputStream(String name)360 	public Object getBufferedFileInputStream(String name) {
361     // n/a for any applet
362     return null;
363   }
364 
365 	@Override
getURLContents(URL url, byte[] outputBytes, String post, boolean asString)366 	public Object getURLContents(URL url, byte[] outputBytes, String post,
367 			boolean asString) {
368 		Object ret = JsFile.getURLContents(url, outputBytes, post);
369 		// check for error
370 		try {
371 			return (!asString ? ret : ret instanceof String ? ret : ret instanceof SB ? ((SB) ret)
372 					.toString() : ret instanceof byte[] ? new String((byte[]) ret)
373 					: new String((byte[]) Rdr.getStreamAsBytes((BufferedInputStream) ret,
374 							null)));
375 		} catch (Exception e) {
376 			return "" + e;
377 		}
378 	}
379 
380 	@Override
getLocalUrl(String fileName)381 	public String getLocalUrl(String fileName) {
382 		// not used in JSpecView
383 		return null;
384 	}
385 
386 	@Override
getImageDialog(String title, Map<String, GenericImageDialog> imageMap)387 	public GenericImageDialog getImageDialog(String title,
388 			Map<String, GenericImageDialog> imageMap) {
389 		// TODO Auto-generated method stub
390 		return null;
391 	}
392 
393   @Override
forceAsyncLoad(String filename)394   public boolean forceAsyncLoad(String filename) {
395     // TODO Auto-generated method stub
396     return false;
397   }
398 
399   @Override
getInChI()400   public JmolInChI getInChI() {
401     // TODO
402     return null;
403   }
404 
405   @Override
confirm(String msg, String msgNo)406   public int confirm(String msg, String msgNo) {
407     boolean ok = /** @j2sNative confirm(msg) || */false;
408     if (ok)
409       return JOptionPane.OK_OPTION;
410     if (msgNo != null)
411       ok =  /** @j2sNative confirm(msgNo) || */false;
412     return (ok ? JOptionPane.NO_OPTION : JOptionPane.CANCEL_OPTION);
413   }
414 
415 
416 }
417