consolidation of Platform isJS calls
[jalview.git] / src / jalview / util / Platform.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.util;
22
23 import java.awt.Toolkit;
24 import java.awt.event.MouseEvent;
25 import java.io.File;
26 import java.util.Properties;
27
28 import javax.swing.SwingUtilities;
29
30 /**
31  * System platform information used by Applet and Application
32  * 
33  * @author Jim Procter
34  */
35 public class Platform
36 {
37
38   private static boolean isJS = /** @j2sNative true || */
39           false;
40
41   private static Boolean isNoJSMac = null, isNoJSWin = null, isMac = null,
42           isWin = null;
43
44   private static Boolean isHeadless = null;
45
46   /**
47    * added to group mouse events into Windows and nonWindows (mac, unix, linux)
48    * 
49    * @return
50    */
51   public static boolean isMac()
52   {
53     return (isMac == null
54             ? (isMac = (System.getProperty("os.name").indexOf("Mac") >= 0))
55             : isMac);
56   }
57
58   /**
59    * added to group mouse events into Windows and nonWindows (mac, unix, linux)
60    * 
61    * @return
62    */
63   public static boolean isWin()
64   {
65     return (isWin == null
66             ? (isWin = (System.getProperty("os.name").indexOf("Win") >= 0))
67             : isWin);
68   }
69
70   /**
71    * 
72    * @return true if HTML5 JavaScript
73    */
74   public static boolean isJS()
75   {
76     return isJS;
77   }
78
79   /**
80    * sorry folks - Macs really are different
81    * 
82    * BH: disabled for SwingJS -- will need to check key-press issues
83    * 
84    * @return true if we do things in a special way.
85    */
86   public static boolean isAMacAndNotJS()
87   {
88     return (isNoJSMac == null ? (isNoJSMac = !isJS && isMac()) : isNoJSMac);
89   }
90
91   /**
92    * Check if we are on a Microsoft plaform...
93    * 
94    * @return true if we have to cope with another platform variation
95    */
96   public static boolean isWindowsAndNotJS()
97   {
98     return (isNoJSWin == null ? (isNoJSWin = !isJS && isWin()) : isNoJSWin);
99   }
100
101   /**
102    * 
103    * @return true if we are running in non-interactive no UI mode
104    */
105   public static boolean isHeadless()
106   {
107     if (isHeadless == null)
108     {
109       isHeadless = "true".equals(System.getProperty("java.awt.headless"));
110     }
111     return isHeadless;
112   }
113
114   /**
115    * 
116    * @return nominal maximum command line length for this platform
117    */
118   public static int getMaxCommandLineLength()
119   {
120     // TODO: determine nominal limits for most platforms.
121     return 2046; // this is the max length for a windows NT system.
122   }
123
124   /**
125    * escape a string according to the local platform's escape character
126    * 
127    * @param file
128    * @return escaped file
129    */
130   public static String escapeString(String file)
131   {
132     StringBuffer f = new StringBuffer();
133     int p = 0, lastp = 0;
134     while ((p = file.indexOf('\\', lastp)) > -1)
135     {
136       f.append(file.subSequence(lastp, p));
137       f.append("\\\\");
138       lastp = p + 1;
139     }
140     f.append(file.substring(lastp));
141     return f.toString();
142   }
143
144   /**
145    * Answers true if the mouse event has Meta-down (Command key on Mac) or
146    * Ctrl-down (on other o/s). Note this answers _false_ if the Ctrl key is
147    * pressed instead of the Meta/Cmd key on Mac. To test for Ctrl-pressed on
148    * Mac, you can use e.isPopupTrigger().
149    * 
150    * @param e
151    * @return
152    */
153   public static boolean isControlDown(MouseEvent e)
154   {
155     return isControlDown(e, isMac());
156   }
157
158   /**
159    * Overloaded version of method (to allow unit testing)
160    * 
161    * @param e
162    * @param aMac
163    * @return
164    */
165   protected static boolean isControlDown(MouseEvent e, boolean aMac)
166   {
167     if (!aMac)
168     {
169       return e.isControlDown();
170     }
171     // answer false for right mouse button
172     // shortcut key will be META for a Mac
173     return !e.isPopupTrigger()
174             && (Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
175                     & e.getModifiers()) != 0;
176     // could we use e.isMetaDown() here?
177   }
178
179   // BH: I don't know about that previous method. Here is what SwingJS uses.
180   // Notice the distinction in mouse events. (BUTTON3_MASK == META)
181   //
182   // private static boolean isPopupTrigger(int id, int mods, boolean isWin) {
183   // boolean rt = ((mods & InputEvent.BUTTON3_MASK) != 0);
184   // if (isWin) {
185   // if (id != MouseEvent.MOUSE_RELEASED)
186   // return false;
187   ////
188   //// // Oddly, Windows returns InputEvent.META_DOWN_MASK on release, though
189   //// // BUTTON3_DOWN_MASK for pressed. So here we just accept both.
190   ////
191   //// actually, we can use XXX_MASK, not XXX_DOWN_MASK and avoid this issue,
192   // because
193   //// J2S adds the appropriate extended (0x3FC0) and simple (0x3F) modifiers.
194   ////
195   // return rt;
196   // } else {
197   // // mac, linux, unix
198   // if (id != MouseEvent.MOUSE_PRESSED)
199   // return false;
200   // boolean lt = ((mods & InputEvent.BUTTON1_MASK) != 0);
201   // boolean ctrl = ((mods & InputEvent.CTRL_MASK) != 0);
202   // return rt || (ctrl && lt);
203   // }
204   // }
205   //
206
207   /**
208    * Windows (not Mac, Linux, or Unix) and right button to test for the
209    * right-mouse pressed event in Windows that would have opened a menu or a
210    * Mac.
211    * 
212    * @param e
213    * @return
214    */
215   public static boolean isWinRightButton(MouseEvent e)
216   {
217     // was !isAMac(), but that is true also for Linux and Unix and JS,
218
219     return isWin() && SwingUtilities.isRightMouseButton(e);
220   }
221
222   /**
223    * Windows (not Mac, Linux, or Unix) and middle button -- for mouse wheeling
224    * without pressing the button.
225    * 
226    * @param e
227    * @return
228    */
229   public static boolean isWinMiddleButton(MouseEvent e)
230   {
231     // was !isAMac(), but that is true also for Linux and Unix and JS
232     return isWin() && SwingUtilities.isMiddleMouseButton(e);
233   }
234
235   public static boolean allowMnemonics()
236   {
237     return !isMac();
238   }
239
240   public final static int TIME_RESET = 0;
241
242   public final static int TIME_MARK = 1;
243
244   public static final int TIME_SET = 2;
245
246   public static final int TIME_GET = 3;
247
248   public static long time, mark, set, duration;
249
250   public static void timeCheck(String msg, int mode)
251   {
252     long t = System.currentTimeMillis();
253     switch (mode)
254     {
255     case TIME_RESET:
256       time = mark = t;
257       if (msg != null)
258       {
259         System.err.println("Platform: timer reset\t\t\t" + msg);
260       }
261       break;
262     case TIME_MARK:
263       if (set > 0)
264       {
265         duration += (t - set);
266       }
267       else
268       {
269         if (time == 0)
270         {
271           time = mark = t;
272         }
273         if (msg != null)
274         {
275           System.err.println("Platform: timer mark\t" + ((t - time) / 1000f)
276                   + "\t" + ((t - mark) / 1000f) + "\t" + msg);
277         }
278         mark = t;
279       }
280       break;
281     case TIME_SET:
282       set = t;
283       break;
284     case TIME_GET:
285       if (msg != null)
286       {
287         System.err.println("Platform: timer dur\t" + ((t - time) / 1000f)
288                 + "\t" + ((duration) / 1000f) + "\t" + msg);
289       }
290       set = 0;
291       break;
292     }
293   }
294
295   public static void cacheFileData(String path, byte[] data)
296   {
297     if (!isJS())
298     {
299       return;
300     }
301     /**
302      * @j2sNative
303      * 
304      *            swingjs.JSUtil.cacheFileData$S$O(path, data);
305      * 
306      */
307   }
308
309   public static byte[] getFileBytes(File f)
310   {
311     return /** @j2sNative f && f._bytes || */
312     null;
313   }
314
315   public static byte[] getFileAsBytes(String fileStr)
316   {
317     // BH 2018 hack for no support for access-origin
318     return /** @j2sNative swingjs.JSUtil.getFileAsBytes$O(fileStr) || */
319     null;
320   }
321
322   public static String getFileAsString(String data)
323   {
324     return /** @j2sNative swingjs.JSUtil.getFileAsString$S(data) || */
325     null;
326   }
327
328   public static boolean setFileBytes(File f, String urlstring)
329   {
330     if (!isJS())
331     {
332       return false;
333     }
334     @SuppressWarnings("unused")
335     byte[] bytes = getFileAsBytes(urlstring);
336     /**
337      * @j2sNative f._bytes = bytes;
338      */
339     return true;
340   }
341
342   public static void addJ2SBinaryType(String ext)
343   {
344     /**
345      * @j2sNative
346      * 
347      *            J2S._binaryTypes.push("." + ext + "?");
348      * 
349      */
350   }
351
352   /**
353    * Encode the URI using JavaScript encodeURIComponent
354    * 
355    * @param value
356    * @return encoded value
357    */
358   public static String encodeURI(String value)
359   {
360     /**
361      * @j2sNative value = encodeURIComponent(value);
362      */
363     return value;
364   }
365
366   /**
367    * Open the URL using a simple window call if this is JavaScript
368    * 
369    * @param url
370    * @return true if window has been opened
371    */
372   public static boolean openURL(String url)
373   {
374     if (!isJS())
375     {
376       return false;
377     }
378     /**
379      * @j2sNative
380      * 
381      * 
382      *            window.open(url);
383      */
384     return true;
385   }
386
387   public static String getUniqueAppletID()
388   {
389     @SuppressWarnings("unused")
390     ThreadGroup g = Thread.currentThread().getThreadGroup();
391     /**
392      * @j2sNative return g.html5Applet._uniqueId;
393      *
394      */
395     return null;
396
397   }
398
399   /**
400    * Read the Info block for this applet.
401    * 
402    * @param prefix
403    *          "jalview_"
404    * @param p
405    * @return unique id for this applet
406    */
407   public static void readInfoProperties(String prefix, Properties p)
408   {
409     @SuppressWarnings("unused")
410     ThreadGroup g = Thread.currentThread().getThreadGroup();
411     String id = getUniqueAppletID();
412     String key = "", value = "";
413     /**
414      * @j2sNative var info = g.html5Applet.__Info || {}; for (var key in info) {
415      *            if (key.indexOf(prefix) == 0) { value = "" + info[key];
416      */
417
418     p.put(id + "_" + key, value);
419
420     /**
421      * @j2sNative
422      * 
423      * 
424      *            } }
425      */
426   }
427
428 }