1 package jspecview.common;
2 
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.OutputStream;
6 import java.net.MalformedURLException;
7 import java.net.URL;
8 import java.util.Arrays;
9 import java.util.Enumeration;
10 import java.util.Hashtable;
11 import java.util.Map;
12 import java.util.Properties;
13 
14 import org.jmol.api.GenericFileInterface;
15 import org.jmol.api.GenericGraphics;
16 import org.jmol.api.GenericPlatform;
17 import org.jmol.api.PlatformViewer;
18 import org.jmol.util.Logger;
19 
20 import javajs.api.BytePoster;
21 import javajs.util.CU;
22 import javajs.util.Lst;
23 import javajs.util.OC;
24 import javajs.util.P3;
25 import javajs.util.PT;
26 import javajs.util.SB;
27 import jspecview.api.ExportInterface;
28 import jspecview.api.JSVFileHelper;
29 import jspecview.api.JSVMainPanel;
30 import jspecview.api.JSVPanel;
31 import jspecview.api.JSVPrintDialog;
32 import jspecview.api.JSVTree;
33 import jspecview.api.JSVTreeNode;
34 import jspecview.api.ScriptInterface;
35 import jspecview.api.VisibleInterface;
36 import jspecview.api.js.JSVAppletObject;
37 import jspecview.api.js.JSVToJSmolInterface;
38 import jspecview.common.Annotation.AType;
39 import jspecview.common.PanelData.LinkMode;
40 import jspecview.common.Spectrum.IRMode;
41 import jspecview.dialog.DialogManager;
42 import jspecview.dialog.JSVDialog;
43 import jspecview.exception.JSVException;
44 import jspecview.popup.JSVGenericPopup;
45 import jspecview.source.JDXReader;
46 import jspecview.source.JDXSource;
47 import jspecview.tree.SimpleTree;
48 
49 /**
50  * This class encapsulates all general functionality of applet and app. Most
51  * methods include ScriptInterface parameter, which will be JSVAppletPrivate,
52  * JSVAppletPrivatePro, or MainFrame.
53  *
54  * @author Bob Hanson hansonr@stolaf.edu
55  *
56  */
57 public class JSViewer implements PlatformViewer, BytePoster {
58 
59   public final static String sourceLabel = "Original...";
60 
61   public final static int FILE_OPEN_OK = 0;
62   public final static int FILE_OPEN_ALREADY = -1;
63   // private final static int FILE_OPEN_URLERROR = -2;
64   public final static int FILE_OPEN_ERROR = -3;
65   public final static int FILE_OPEN_NO_DATA = -4;
66   public static final int OVERLAY_DIALOG = -1;
67   public static final int OVERLAY_OFFSET = 99;
68   public static final int PORTRAIT = 1; // Printable
69   public static final int PAGE_EXISTS = 0;
70   public static final int NO_SUCH_PAGE = 1;
71 
72   private static String testScript = "<PeakData  index=\"1\" title=\"\" model=\"~1.1\" type=\"1HNMR\" xMin=\"3.2915\" xMax=\"3.2965\" atoms=\"15,16,17,18,19,20\" multiplicity=\"\" integral=\"1\"> src=\"JPECVIEW\" file=\"http://SIMULATION/$caffeine\"";
73 
74   private final static int NLEVEL_MAX = 100;
75 
76   public ScriptInterface si;
77   public GenericGraphics g2d;
78   public JSVTree spectraTree;
79   public JDXSource currentSource;
80   public Lst<PanelNode> panelNodes;
81   public ColorParameters parameters;
82   public RepaintManager repaintManager;
83   public JSVPanel selectedPanel;
84   public JSVMainPanel mainPanel;
85   public Properties properties; // application only
86   public Lst<String> scriptQueue;
87   public JSVFileHelper fileHelper;
88   public JSVGenericPopup jsvpPopupMenu;
89   private DialogManager dialogManager;
90   private JSVDialog viewDialog;
91   private JSVDialog overlayLegendDialog;
92 
93   private IRMode irMode = IRMode.NO_CONVERT;
94 
95   public boolean loadImaginary;
96   public boolean interfaceOverlaid;
97   public boolean autoIntegrate;
98   public boolean autoShowLegend;
99   public Boolean obscureTitleFromUser;
100   //  public boolean allowCompoundMenu = true;
101   public boolean allowMenu = true;
102   public int initialStartIndex = -1;
103   public int initialEndIndex = -1;
104 
105   public boolean isSingleThreaded;
106   public boolean isApplet;
107   public static boolean isJS, isSwingJS = false;
108   public boolean isSigned;
109 
110   private String recentScript = "";
111 
112   public String appletName;
113   public String fullName;
114   public String syncID;
115   public JSVAppletObject html5Applet; // will be an JavaScript object if this is JavaScript
116 
117   public Object display;
118 
119   private int maximumSize = Integer.MAX_VALUE;
120   private int screenHeight, screenWidth;
121   private int fileCount;
122   private int nViews;
123   private int scriptLevelCount;
124   private String returnFromJmolModel;
125   private String integrationRatios;
126 
127   public GenericPlatform apiPlatform;
128 
129   public static JSVToJSmolInterface jmolObject;
130 
setProperty(String key, String value)131   public void setProperty(String key, String value) {
132     if (properties != null)
133       properties.setProperty(key, value);
134   }
135 
setNode(PanelNode node)136   public void setNode(PanelNode node) {
137     if (node.jsvp != selectedPanel)
138       si.siSetSelectedPanel(node.jsvp);
139     si.siSendPanelChange();
140     si.siNodeSet(node);
141   }
142 
143   /**
144    * @param si
145    * @param isApplet
146    * @param isJSApplet
147    */
JSViewer(ScriptInterface si, boolean isApplet, boolean isJSApplet)148   public JSViewer(ScriptInterface si, boolean isApplet, boolean isJSApplet) {
149     this.si = si;
150     this.isApplet = isApplet;
151     isJS = isApplet && isJSApplet;
152     JSVToJSmolInterface jmol = null;
153 
154     /**
155      * @j2sNative
156      *
157      * self.Jmol && (jmol = Jmol);
158      *
159      */
160     {
161 
162     }
163     jmolObject = jmol;
164     this.isSigned = si.isSigned();
165     apiPlatform = (GenericPlatform) getPlatformInterface("Platform");
166     apiPlatform.setViewer(this, this.display);
167     g2d = (GenericGraphics) getPlatformInterface("G2D");
168     spectraTree = new SimpleTree(this);
169     parameters = (ColorParameters) getPlatformInterface("Parameters");
170     parameters.setName("applet");
171     fileHelper = ((JSVFileHelper) getPlatformInterface("FileHelper")).set(this);
172     isSingleThreaded = apiPlatform.isSingleThreaded();
173     panelNodes = new Lst<PanelNode>();
174     repaintManager = new RepaintManager(this);
175     if (!isApplet)
176       setPopupMenu(true, true);
177   }
178 
179   private boolean popupAllowMenu = true;
180   private boolean popupZoomEnabled = true;
181 
182   private String defaultLoadScript;
183 
184   public float nmrMaxY = Float.NaN;
185 
setPopupMenu(boolean allowMenu, boolean zoomEnabled)186   public void setPopupMenu(boolean allowMenu, boolean zoomEnabled) {
187     popupAllowMenu = allowMenu;
188     popupZoomEnabled = zoomEnabled;
189   }
190 
showMenu(int x, int y)191   public void showMenu(int x, int y) {
192     if (!popupAllowMenu)
193       return;
194     if (jsvpPopupMenu == null) {
195       try {
196         jsvpPopupMenu = (JSVGenericPopup) getPlatformInterface("Popup");
197         jsvpPopupMenu.jpiInitialize(this, isApplet ? "appletMenu" : "appMenu");
198         jsvpPopupMenu.setEnabled(popupAllowMenu, popupZoomEnabled);
199       } catch (Exception e) {
200         Logger.error(e + " initializing popup menu");
201         return;
202       }
203     }
204     jsvpPopupMenu.jpiShow(x, y);
205   }
206 
runScriptNow(String script)207   public boolean runScriptNow(String script) {
208     System.out.println(checkScript(script));
209     scriptLevelCount++;
210     if (script == null)
211       script = "";
212     script = script.trim();
213     if (script.startsWith("!"))
214       script = script.substring(1).trim();
215     else if (script.startsWith(">")) {
216       Logger.error(script);
217       return true;
218     }
219     if (script.indexOf("<PeakData") >= 0) {
220       syncScript(script);
221       return true;
222     }
223     Logger.info("RUNSCRIPT " + script);
224     boolean isOK = true;
225     int nErrorsLeft = 10;
226     ScriptTokenizer commandTokens = new ScriptTokenizer(script, true);
227     String msg = null;
228     while (commandTokens != null && commandTokens.hasMoreTokens()
229         && nErrorsLeft > 0 && isOK) {
230       String token = commandTokens.nextToken();
231       // now split the key/value pair
232 
233       ScriptTokenizer eachParam = new ScriptTokenizer(token, false);
234       String key = ScriptToken.getKey(eachParam);
235       if (key == null)
236         continue;
237       ScriptToken st = ScriptToken.getScriptToken(key);
238       String value = ScriptToken.getValue(st, eachParam, token);
239       // System.out.println("KEY-> " + key + " VALUE-> " + value + " : " + st);
240       try {
241         switch (st) {
242         case UNKNOWN:
243           Logger.info("Unrecognized parameter: " + key);
244           --nErrorsLeft;
245           break;
246         default:
247           if (selectedPanel == null)
248             break;// probably a startup option for the applet
249           parameters.set(pd(), st, value);
250           si.siUpdateBoolean(st, Parameters.isTrue(value));
251           break;
252         case PEAKCALLBACKFUNCTIONNAME:
253         case SYNCCALLBACKFUNCTIONNAME:
254         case COORDCALLBACKFUNCTIONNAME:
255         case LOADFILECALLBACKFUNCTIONNAME:
256           si.siExecSetCallback(st, value);
257           break;
258         case DEFAULTLOADSCRIPT:
259           value = PT.rep(value, "''", "\"");
260           defaultLoadScript = (value.length() > 0 ? value : null);
261           break;
262         case DEFAULTNMRNORMALIZATION:
263           nmrMaxY = PT.parseFloat(value);
264           break;
265         case AUTOINTEGRATE:
266           autoIntegrate = Parameters.isTrue(value);
267           break;
268         case CLOSE:
269           execClose(value);
270           break;
271         case DEBUG:
272           Logger
273               .setLogLevel(value.toLowerCase().equals("high") ? Logger.LEVEL_DEBUGHIGH
274                   : Parameters.isTrue(value) ? Logger.LEVEL_DEBUG
275                       : Logger.LEVEL_INFO);
276           break;
277         case GETPROPERTY:
278           Map<String, Object> info = (selectedPanel == null ? null
279               : getPropertyAsJavaObject(value));
280           if (info != null)
281             selectedPanel.showMessage(PT.toJSON(null, info), value);
282           break;
283         case HELP:
284           execHelp(value);
285           break;
286         case HIDDEN:
287           si.siExecHidden(Parameters.isTrue(value));
288           break;
289         case INTEGRATIONRATIOS:
290           integrationRatios = value;
291           execIntegrate(null);
292           break;
293         case INTERFACE:
294           interfaceOverlaid = checkOvelayInterface(value);
295           break;
296         case INTEGRALOFFSET:
297         case INTEGRALRANGE:
298           execSetIntegralParameter(st, Double.parseDouble(value));
299           break;
300         case INVERTY:
301           execZoom("invertY");
302           break;
303         case JMOL:
304           si.syncToJmol(value);
305           break;
306         case JSV:
307           syncScript(PT.trimQuotes(value));
308           break;
309         case LOAD:
310           if (value.length() == 0) {
311             if (defaultLoadScript != null)
312               runScriptNow(defaultLoadScript);
313             break;
314           }
315           execLoad(value, (defaultLoadScript == null ? "" : defaultLoadScript
316               + ";")
317               + commandTokens.getRemainingScript());
318           msg = (selectedPanel == null ? null : si.siLoaded(value));
319           commandTokens = null;
320           break;
321         case LOADIMAGINARY:
322           loadImaginary = Parameters.isTrue(value);
323           break;
324         case PEAK:
325           execPeak(value);
326           break;
327         case PEAKLIST:
328           execPeakList(value);
329           break;
330         case SCALEBY:
331           scaleSelectedBy(panelNodes, value);
332           break;
333         case SCRIPT:
334           if (value.equals("") || value.toLowerCase().startsWith("inline")) {
335             execScriptInline(value);
336           } else {
337             String s = JSVFileManager.getFileAsString(value);
338             if (s != null && scriptLevelCount < NLEVEL_MAX)
339               runScriptNow(s);
340           }
341           break;
342         case SELECT:
343           execSelect(value);
344           break;
345         case SPECTRUM:
346         case SPECTRUMNUMBER:
347           if (!setSpectrum(value))
348             isOK = false;
349           break;
350         case STACKOFFSETY:
351           execOverlayOffsetY(PT.parseInt("" + PT.parseFloat(value)));
352           break;
353         case TEST:
354           si.siExecTest(value);
355           break;
356         case OVERLAY: // deprecated
357         case VIEW:
358           execView(value, true);
359           break;
360         case HIGHLIGHT:
361           isOK = highlight(token);
362           break;
363         case FINDX:
364         case GETSOLUTIONCOLOR:
365         case INTEGRATION:
366         case INTEGRATE:
367         case IRMODE:
368         case LABEL:
369         case LINK:
370         case OVERLAYSTACKED:
371         case PRINT:
372         case SETPEAK:
373         case SETX:
374         case SHIFTX:
375         case SHOWERRORS:
376         case SHOWMEASUREMENTS:
377         case SHOWMENU:
378         case SHOWKEY:
379         case SHOWPEAKLIST:
380         case SHOWINTEGRATION:
381         case SHOWPROPERTIES:
382         case SHOWSOURCE:
383         case YSCALE:
384         case WRITE:
385         case ZOOM:
386           if (isClosed()) {
387             isOK = false;
388             break;
389           }
390           switch (st) {
391           default:
392             break;
393           case FINDX:
394             pd().findX(null, Double.parseDouble(value));
395             break;
396           case GETSOLUTIONCOLOR:
397             show("solutioncolor" + value.toLowerCase());
398             break;
399           case INTEGRATION:
400           case INTEGRATE:
401             execIntegrate(value);
402             break;
403           case IRMODE:
404             execIRMode(value);
405             break;
406           case LABEL:
407             pd().addAnnotation(ScriptToken.getTokens(value));
408             break;
409           case LINK:
410             pd().linkSpectra(LinkMode.getMode(value));
411             break;
412           case OVERLAYSTACKED:
413             pd().splitStack(!Parameters.isTrue(value));
414             break;
415           case PRINT:
416             msg = execWrite(null);
417             break;
418           case SETPEAK:
419           case SETX:
420           case SHIFTX:
421             execShiftSpectrum(st, token);
422             break;
423           case SHOWERRORS:
424             show("errors");
425             break;
426           case SHOWINTEGRATION:
427             pd().showAnnotation(AType.Integration,
428                 Parameters.getTFToggle(value));
429             // execIntegrate(null);
430             break;
431           case SHOWKEY:
432             setOverlayLegendVisibility(Parameters.getTFToggle(value), true);
433             break;
434           case SHOWMEASUREMENTS:
435             pd().showAnnotation(AType.Measurements,
436                 Parameters.getTFToggle(value));
437             break;
438           case SHOWMENU:
439             showMenu(Integer.MIN_VALUE, 0);
440             break;
441           case SHOWPEAKLIST:
442             pd().showAnnotation(AType.PeakList, Parameters.getTFToggle(value));
443             break;
444           case SHOWPROPERTIES:
445             show("properties");
446             break;
447           case SHOWSOURCE:
448             show("source");
449             break;
450           case YSCALE:
451             setYScale(value);
452             break;
453           case WINDOW:
454             si.siNewWindow(Parameters.isTrue(value), false);
455             break;
456           case WRITE:
457             msg = execWrite(value);
458             break;
459           case ZOOM:
460             isOK = execZoom(value);
461             break;
462           }
463           break;
464         }
465       } catch (Exception e) {
466         msg = e.toString();
467         Logger.error(e.toString());
468         isOK = false;
469         --nErrorsLeft;
470       }
471     }
472     scriptLevelCount--;
473     si.siExecScriptComplete(msg, true);
474     return isOK;
475   }
476 
execShiftSpectrum(ScriptToken st, String script)477   private void execShiftSpectrum(ScriptToken st, String script) {
478     Lst<String> tokens = ScriptToken.getTokens(script);
479     double xOld = Double.NaN;
480     double xNew = Double.NaN;
481     switch (tokens.size()) {
482     case 2:
483       String value = tokens.get(1);
484       if (value.equals(""))
485         value = "?";
486       xNew = value.equalsIgnoreCase("NONE") ? Double.MAX_VALUE : value
487           .equalsIgnoreCase("?") ? Double.NaN : Double.parseDouble(value);
488       break;
489     case 3:
490       xOld = Double.parseDouble(tokens.get(1));
491       xNew = Double.parseDouble(tokens.get(2));
492       break;
493     default:
494       Double.parseDouble(""); // throw an exception
495     }
496     int mode = 0;
497     switch (st) {
498     case SETPEAK:
499       mode = GraphSet.SHIFT_PEAK;
500       break;
501     case SETX:
502       mode = GraphSet.SHIFT_SETX;
503       break;
504     case SHIFTX:
505       mode = GraphSet.SHIFT_X;
506       if (Double.isNaN(xNew))
507         Double.parseDouble(""); // throw an exception -- SHIFT by itself not
508                                 // allowed
509       break;
510     default:
511       return;
512     }
513     pd().shiftSpectrum(mode, xOld, xNew);
514   }
515 
execClose(String value)516   private void execClose(String value) {
517     boolean fromScript = (!value.startsWith("!"));
518     if (!fromScript)
519       value = value.substring(1);
520     close(PT.trimQuotes(value));
521     if (!fromScript || panelNodes.size() == 0)
522       si.siValidateAndRepaint(true);
523   }
524 
checkOvelayInterface(String value)525   public boolean checkOvelayInterface(String value) {
526     return (value.equalsIgnoreCase("single") || value
527         .equalsIgnoreCase("overlay"));
528   }
529 
execPeak(String value)530   private void execPeak(String value) {
531     try {
532       Lst<String> tokens = ScriptToken.getTokens(PT.rep(value, "#", "INDEX="));
533       value = " type=\"" + tokens.get(0).toUpperCase() + "\" _match=\""
534           + PT.trimQuotes(tokens.get(1).toUpperCase()) + "\"";
535       if (tokens.size() > 2 && tokens.get(2).equalsIgnoreCase("all"))
536         value += " title=\"ALL\"";
537       processPeakPickEvent(new PeakInfo(value), false); // false == true here
538     } catch (Exception e) {
539       // ignore
540     }
541   }
542 
execPeakList(String value)543   private void execPeakList(String value) {
544     ColorParameters p = parameters;
545     Boolean b = Parameters.getTFToggle(value);
546     if (value.indexOf("=") < 0) {
547       if (!isClosed())
548         pd().getPeakListing(null, b);
549     } else {
550       Lst<String> tokens = ScriptToken.getTokens(value);
551       double threshold = p.peakListThreshold;
552       String interp = p.peakListInterpolation;
553       try {
554         for (int i = tokens.size(); --i >= 0;) {
555           String token = tokens.get(i);
556           int pt = token.indexOf("=");
557           if (pt <= 0)
558             continue;
559           String key = token.substring(0, pt);
560           value = token.substring(pt + 1);
561           if (key.startsWith("thr")) {
562             threshold = Double.valueOf(value).doubleValue();
563           } else if (key.startsWith("int")) {
564             interp = (value.equalsIgnoreCase("none") ? "NONE" : "parabolic");
565           }
566         }
567         p.peakListThreshold = threshold;
568         p.peakListInterpolation = interp;
569         if (!isClosed())
570           pd().getPeakListing(p, Boolean.TRUE);
571       } catch (Exception e) {
572         // ignore
573       }
574     }
575   }
576 
highlight(String value)577   private boolean highlight(String value) {
578     Lst<String> tokens = ScriptToken.getTokens(value);
579     int n = tokens.size();
580     switch (n) {
581     case 3:
582     case 5:
583     case 6:
584     case 7:
585       break;
586     case 2:
587     case 4:
588       if (tokens.get(n - 1).equalsIgnoreCase("OFF"))
589         break;
590       //$FALL-THROUGH$
591     default:
592       return false;
593     }
594     if (!isClosed()) {
595       float x1 = PT.parseFloat(n > 1 ? tokens.get(1) : "");
596       float x2 = PT.parseFloat(n > 2 ? tokens.get(2) : "");
597       int r = getRGB(n > 3 ? tokens.get(3) : "100");
598       int g = getRGB(n > 4 ? tokens.get(4) : "100");
599       int b = getRGB(n > 5 ? tokens.get(5) : "100");
600       int a = getRGB(n > 6 ? tokens.get(6) : "100");
601       if (Float.isNaN(x1) || Float.isNaN(x2)) {
602         pd().removeAllHighlights();
603       } else {
604         pd().removeHighlight(x1, x2);
605         if (a < 0)
606           a = 150;
607         if (r >= 0 && g >= 0 && b >= 0)
608           pd().addHighlight(null, x1, x2, null, r, g, b, a);
609       }
610       repaint(true);
611     }
612     return true;
613   }
614 
getRGB(String s)615   private int getRGB(String s) {
616     float f = PT.parseFloat(s);
617     return (int) (Float.isNaN(f) ? -1 : f > 1 ? f : f * 255);
618   }
619 
execZoom(String value)620   private boolean execZoom(String value) {
621     double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
622     value = PT.rep(value, " - ", " ").replace(',', ' ');
623     Lst<String> tokens = ScriptToken.getTokens(value);
624     switch (tokens.size()) {
625     default:
626       return false;
627     case 0:
628       ScaleData v = pd().getCurrentGraphSet().getCurrentView();
629       value = Math.round(v.minXOnScale * 100) / 100f + ","
630           + Math.round(v.maxXOnScale * 100) / 100f;
631       value = selectedPanel.getInput("Enter zoom range x1 x2", "Zoom", value);
632       return (value == null || execZoom(value));
633     case 1:
634       value = tokens.get(0);
635       if (value.equalsIgnoreCase("next")) {
636         pd().nextView();
637       } else if (value.toLowerCase().startsWith("prev")) {
638         pd().previousView();
639       } else if (value.equalsIgnoreCase("out")) {
640         pd().resetView();
641       } else if (value.equalsIgnoreCase("clear")) {
642         pd().clearAllView();
643       } else if (value.equalsIgnoreCase("invertY")) {
644         pd().getCurrentGraphSet().invertYAxis();
645       }
646       return true;
647     case 2:
648       x1 = Double.parseDouble(tokens.get(0));
649       x2 = Double.parseDouble(tokens.get(1));
650       break;
651     case 3:
652       String xy = tokens.get(0);
653       if (xy.equalsIgnoreCase("X")) {
654         x1 = Double.parseDouble(tokens.get(1));
655         x2 = Double.parseDouble(tokens.get(2));
656       } else if (xy.equalsIgnoreCase("Y")) {
657         y1 = Double.parseDouble(tokens.get(1));
658         y2 = Double.parseDouble(tokens.get(2));
659       }
660       break;
661     case 4:
662       x1 = Double.parseDouble(tokens.get(0));
663       y1 = Double.parseDouble(tokens.get(1));
664       x2 = Double.parseDouble(tokens.get(2));
665       y2 = Double.parseDouble(tokens.get(3));
666     }
667     pd().setZoom(x1, y1, x2, y2);
668     return true;
669   }
670 
scaleSelectedBy(Lst<PanelNode> nodes, String value)671   private void scaleSelectedBy(Lst<PanelNode> nodes, String value) {
672     try {
673       double f = Double.parseDouble(value);
674       for (int i = nodes.size(); --i >= 0;)
675         nodes.get(i).pd().scaleSelectedBy(f);
676     } catch (Exception e) {
677     }
678   }
679 
pd()680   public PanelData pd() {
681     return (selectedPanel == null ? null : selectedPanel.getPanelData());
682   }
683 
isClosed()684   private boolean isClosed() {
685     return (pd() == null);
686   }
687 
execSelect(String value)688   private void execSelect(String value) {
689     if (value.startsWith("ID ")) {
690       if (!isClosed())
691         try {
692           pd().selectSpectrum(null, "ID", PT.trimQuotes(value.substring(3)),
693               true);
694         } catch (Exception e) {
695           //
696         }
697       return;
698     }
699     Lst<PanelNode> nodes = panelNodes;
700     for (int i = nodes.size(); --i >= 0;)
701       nodes.get(i).pd().selectFromEntireSet(Integer.MIN_VALUE);
702     Lst<Spectrum> speclist = new Lst<Spectrum>();
703     fillSpecList(value, speclist, false);
704     // not sure where this is going...
705   }
706 
execView(String value, boolean fromScript)707   public void execView(String value, boolean fromScript) {
708     if (value.equals("")) {
709       checkOverlay();
710       return;
711     }
712     Lst<Spectrum> speclist = new Lst<Spectrum>();
713     String strlist = fillSpecList(value, speclist, true);
714     if (speclist.size() > 0)
715       si.siOpenDataOrFile(null, strlist, speclist, strlist, -1, -1, false,
716           null, null);
717     if (!fromScript) {
718       si.siValidateAndRepaint(false);
719     }
720   }
721 
execIRMode(String value)722   private void execIRMode(String value) {
723     IRMode mode = IRMode.getMode(value); // T, A, or TOGGLE
724     String type = pd().getSpectrum().dataType;
725     for (int i = panelNodes.size(); --i >= 0;)
726       panelNodes.get(i).pd().setIRMode(mode, type);
727     setIRmode(value);
728     // jsvp.doRepaint();
729   }
730 
execIntegrate(String value)731   private void execIntegrate(String value) {
732     if (isClosed())
733       return;
734     pd().checkIntegral(parameters, value);
735     if (integrationRatios != null)
736       pd().setIntegrationRatios(integrationRatios);
737     integrationRatios = null; // one time only
738     repaint(true);
739   }
740 
repaint(boolean andTaintAll)741   private void repaint(boolean andTaintAll) {
742     selectedPanel.doRepaint(andTaintAll);
743   }
744 
745   @SuppressWarnings("incomplete-switch")
execSetIntegralParameter(ScriptToken st, double value)746   private void execSetIntegralParameter(ScriptToken st, double value) {
747     ColorParameters p = parameters;
748     switch (st) {
749     case INTEGRALRANGE:
750       p.integralRange = value;
751       break;
752     case INTEGRALOFFSET:
753       p.integralOffset = value;
754       break;
755     }
756     if (!isClosed())
757       pd().checkIntegral(parameters, "update");
758   }
759 
setYScale(String value)760   private void setYScale(String value) {
761     Lst<String> tokens = ScriptToken.getTokens(value);
762     int pt = 0;
763     boolean isAll = false;
764     if (tokens.size() > 1 && tokens.get(0).equalsIgnoreCase("ALL")) {
765       isAll = true;
766       pt++;
767     }
768     double y1 = Double.parseDouble(tokens.get(pt++));
769     double y2 = Double.parseDouble(tokens.get(pt));
770     if (isAll) {
771       Spectrum spec = pd().getSpectrum();
772       for (int i = panelNodes.size(); --i >= 0;) {
773         PanelNode node = panelNodes.get(i);
774         if (node.source != currentSource)
775           continue;
776         if (Spectrum.areXScalesCompatible(spec, node.getSpectrum(), false,
777             false))
778           node.pd().setZoom(0, y1, 0, y2);
779       }
780     } else {
781       pd().setZoom(0, y1, 0, y2);
782     }
783   }
784 
785   private boolean overlayLegendVisible;
786 
setOverlayLegendVisibility(Boolean tftoggle, boolean doSet)787   private void setOverlayLegendVisibility(Boolean tftoggle, boolean doSet) {
788     if (doSet)
789       overlayLegendVisible = (tftoggle == null ? !overlayLegendVisible
790           : tftoggle == Boolean.TRUE);
791     PanelNode node = PanelNode.findNode(selectedPanel, panelNodes);
792     for (int i = panelNodes.size(); --i >= 0;)
793       showOverlayLegend(panelNodes.get(i), panelNodes.get(i) == node
794           && overlayLegendVisible);
795   }
796 
showOverlayLegend(PanelNode node, boolean visible)797   private void showOverlayLegend(PanelNode node, boolean visible) {
798     JSVDialog legend = node.legend;
799     if (legend == null && visible) {
800       legend = node.setLegend(node.pd().getNumberOfSpectraInCurrentSet() > 1
801           && node.pd().getNumberOfGraphSets() == 1 ? getDialog(
802           AType.OverlayLegend, null) : null);
803     }
804     if (legend != null)
805       legend.setVisible(visible);
806   }
807 
808   // / from JavaScript
809 
810   /**
811    * incoming script processing of <PeakAssignment file="" type="xxx"...> record
812    * from Jmol
813    *
814    * @param peakScript
815    */
816 
syncScript(String peakScript)817   public void syncScript(String peakScript) {
818     if (peakScript.equals("TEST"))
819       peakScript = testScript;
820     Logger.info("JSViewer.syncScript Jmol>JSV " + peakScript);
821     if (peakScript.indexOf("<PeakData") < 0) {
822       if (peakScript.startsWith("JSVSTR:")) {
823         si.syncToJmol(peakScript);
824         return;
825       }
826       runScriptNow(peakScript);
827       if (peakScript.indexOf("#SYNC_PEAKS") >= 0)
828         syncPeaksAfterSyncScript();
829       return;
830     }
831     Logger.info(">>toJSV>> " + peakScript);
832     String sourceID = PT.getQuotedAttribute(peakScript, "sourceID");
833     String type, model, file, jmolSource, index, atomKey;
834     if (sourceID == null) {
835       // todo: why the quotes??
836       //peakScript = PT.rep(peakScript, "\\\"", "");
837       file = PT.getQuotedAttribute(peakScript, "file");
838       index = PT.getQuotedAttribute(peakScript, "index");
839       if (file == null || index == null)
840         return;
841       file = PT.rep(file, "#molfile", "");// Jmol has loaded the model from the cache
842       model = PT.getQuotedAttribute(peakScript, "model");
843       jmolSource = PT.getQuotedAttribute(peakScript, "src");
844       String modelSent = (jmolSource != null && jmolSource.startsWith("Jmol") ? null
845           : returnFromJmolModel);
846       if (model != null && modelSent != null && !model.equals(modelSent)) {
847         Logger.info("JSV ignoring model " + model + "; should be " + modelSent);
848         return;
849       }
850       returnFromJmolModel = null;
851       if (panelNodes.size() == 0 || !checkFileAlreadyLoaded(file)) {
852         Logger.info("file " + file
853             + " not found -- JSViewer closing all and reopening");
854         si.siSyncLoad(file);
855       }
856       type = PT.getQuotedAttribute(peakScript, "type");
857       atomKey = null;
858     } else {
859       file = null;
860       index = model = sourceID;
861       atomKey = "," + PT.getQuotedAttribute(peakScript, "atom") + ",";
862       type = "ID";
863       jmolSource = sourceID; //??
864     }
865 
866     PeakInfo pi = selectPanelByPeak(file, index, atomKey);
867     PanelData pd = pd();
868     pd.selectSpectrum(file, type, model, true);
869     si.siSendPanelChange();
870     pd.addPeakHighlight(pi);
871     repaint(true);
872     // round trip this so that Jmol highlights all equivalent atoms
873     // and appropriately starts or clears vibration
874     if (jmolSource == null || (pi != null && pi.getAtoms() != null))
875       si.syncToJmol(jmolSelect(pi));
876   }
877 
syncPeaksAfterSyncScript()878   private void syncPeaksAfterSyncScript() {
879     JDXSource source = currentSource;
880     if (source == null)
881       return;
882     try {
883       String file = "file=" + PT.esc(source.getFilePath());
884       Lst<PeakInfo> peaks = source.getSpectra().get(0).getPeakList();
885       SB sb = new SB();
886       sb.append("[");
887       int n = peaks.size();
888       for (int i = 0; i < n; i++) {
889         String s = peaks.get(i).toString();
890         s = s + " " + file;
891         sb.append(PT.esc(s));
892         if (i > 0)
893           sb.append(",");
894       }
895       sb.append("]");
896       si.syncToJmol("Peaks: " + sb);
897     } catch (Exception e) {
898       // ignore bad structures -- no spectrum
899     }
900   }
901 
checkFileAlreadyLoaded(String fileName)902   private boolean checkFileAlreadyLoaded(String fileName) {
903     if (isClosed())
904       return false;
905     if (pd().hasFileLoaded(fileName))
906       return true;
907     for (int i = panelNodes.size(); --i >= 0;)
908       if (panelNodes.get(i).pd().hasFileLoaded(fileName)) {
909         si.siSetSelectedPanel(panelNodes.get(i).jsvp);
910         return true;
911       }
912     return false;
913   }
914 
915   /**
916    * @param file
917    * @param index
918    * @param atomKey
919    * @return PeakInfo entry if appropriate
920    */
selectPanelByPeak(String file, String index, String atomKey)921   private PeakInfo selectPanelByPeak(String file, String index, String atomKey) {
922     if (panelNodes == null)
923       return null;
924     PeakInfo pi = null;
925     for (int i = panelNodes.size(); --i >= 0;)
926       panelNodes.get(i).pd().addPeakHighlight(null);
927     pi = pd().selectPeakByFileIndex(file, index, atomKey);
928     if (pi != null) {
929       // found in current panel
930       setNode(PanelNode.findNode(selectedPanel, panelNodes));
931     } else {
932       // must look elsewhere
933       for (int i = panelNodes.size(); --i >= 0;) {
934         PanelNode node = panelNodes.get(i);
935         if ((pi = node.pd().selectPeakByFileIndex(file, index, atomKey)) != null) {
936           setNode(node);
937           break;
938         }
939       }
940     }
941     return pi;
942   }
943 
944   /**
945    * this method is called as a result of the user clicking on a peak
946    * (eventObject instanceof PeakPickEvent) or from PEAK command execution
947    *
948    * @param eventObj
949    * @param isApp
950    */
processPeakPickEvent(Object eventObj, boolean isApp)951   public void processPeakPickEvent(Object eventObj, boolean isApp) {
952     // trouble here is with round trip when peaks are clicked in rapid
953     // succession.
954 
955     PeakInfo pi;
956     if (eventObj instanceof PeakInfo) {
957       // this is a call from the PEAK command, above.
958       pi = (PeakInfo) eventObj;
959       PeakInfo pi2 = pd().findMatchingPeakInfo(pi);
960       if (pi2 == null) {
961         if (!"ALL".equals(pi.getTitle()))
962           return;
963         PanelNode node = null;
964         for (int i = 0; i < panelNodes.size(); i++)
965           if ((pi2 = panelNodes.get(i).pd().findMatchingPeakInfo(pi)) != null) {
966             node = panelNodes.get(i);
967             break;
968           }
969         if (node == null)
970           return;
971         setNode(node);
972       }
973       pi = pi2;
974     } else {
975       PeakPickEvent e = ((PeakPickEvent) eventObj);
976       si.siSetSelectedPanel((JSVPanel) e.getSource());
977       pi = e.getPeakInfo();
978     }
979     pd().addPeakHighlight(pi);
980     // the above line is what caused problems with GC/MS selection
981     syncToJmol(pi);
982     // System.out.println(Thread.currentThread() +
983     // "processPeakEvent --selectSpectrum " + pi);
984     if (pi.isClearAll()) // was not in app version??
985       repaint(false);
986     else
987       pd().selectSpectrum(pi.getFilePath(), pi.getType(), pi.getModel(), true);
988     si.siCheckCallbacks(pi.getTitle());
989   }
990 
newStructToJmol(String data)991   void newStructToJmol(String data) {
992     Logger.info("sending new structure to Jmol:\n" + data);
993     si.syncToJmol("struct:" + data);
994   }
995 
syncToJmol(PeakInfo pi)996   private void syncToJmol(PeakInfo pi) {
997     repaint(true);
998     returnFromJmolModel = pi.getModel();
999     si.syncToJmol(jmolSelect(pi));
1000   }
1001 
sendPanelChange()1002   public void sendPanelChange() {
1003     PanelData pd = pd();
1004     Spectrum spec = pd.getSpectrum();
1005     PeakInfo pi = spec.getSelectedPeak();
1006     if (pi == null)
1007       pi = spec.getModelPeakInfoForAutoSelectOnLoad();
1008     if (pi == null)
1009       pi = spec.getBasePeakInfo();
1010     pd.addPeakHighlight(pi);
1011     Logger.info(Thread.currentThread() + "JSViewer sendFrameChange "
1012         + selectedPanel);
1013     syncToJmol(pi);
1014   }
1015 
jmolSelect(PeakInfo pi)1016   private String jmolSelect(PeakInfo pi) {
1017     String script = ("IR".equals(pi.getType()) || "RAMAN".equals(pi.getType()) ? "vibration ON; selectionHalos OFF;"
1018         : "vibration OFF; selectionhalos "
1019             + (pi.getAtoms() == null ? "OFF" : "ON"));
1020     return "Select: " + pi + " script=\"" + script + " \" sourceID=\""
1021         + pd().getSpectrum().sourceID + "\"";
1022   }
1023 
getPropertyAsJavaObject(String key)1024   public Map<String, Object> getPropertyAsJavaObject(String key) {
1025 
1026     Map<String, Object> map = new Hashtable<String, Object>();
1027 
1028     if ("SOURCEID".equalsIgnoreCase(key)) {
1029       // get current spectrum ID
1030       map.put(key, (pd() == null ? "" : pd().getSpectrum().sourceID));
1031       return map;
1032     }
1033     if (key != null && key.startsWith("DATA_")) {
1034       // mol, json, xml, jcamp -- most recent only
1035       map.put(key, "" + JSVFileManager.cacheGet(key.substring(5)));
1036       return map;
1037     }
1038 
1039     boolean isAll = false;
1040     if (key != null && key.toUpperCase().startsWith("ALL ")
1041         || "all".equalsIgnoreCase(key)) {
1042       key = key.substring(3).trim();
1043       isAll = true;
1044     }
1045     if ("".equals(key))
1046       key = null;
1047     if ("NAMES".equalsIgnoreCase(key) || "KEYS".equalsIgnoreCase(key))
1048       key = "";
1049     Map<String, Object> map0 = pd().getInfo(true, key);
1050     if (!isAll && map0 != null)
1051       return map0;
1052     if (map0 != null)
1053       map.put("current", map0);
1054     Lst<Map<String, Object>> info = new Lst<Map<String, Object>>();
1055     for (int i = 0; i < panelNodes.size(); i++) {
1056       JSVPanel jsvp = panelNodes.get(i).jsvp;
1057       if (jsvp == null)
1058         continue;
1059       info.addLast(panelNodes.get(i).getInfo(key));
1060     }
1061     map.put("items", info);
1062     return map;
1063   }
1064 
getCoordinate()1065   public String getCoordinate() {
1066     if (!isClosed()) {
1067       Coordinate coord = pd().getClickedCoordinate();
1068       if (coord != null)
1069         return coord.getXVal() + " " + coord.getYVal();
1070     }
1071     return "";
1072   }
1073 
1074   /**
1075    * originally in MainFrame, this method takes the OVERLAY command option and
1076    * converts it to a list of spectra
1077    *
1078    * @param value
1079    * @param speclist
1080    * @param isView
1081    * @return comma-separated list, for the title
1082    */
fillSpecList(String value, Lst<Spectrum> speclist, boolean isView)1083   private String fillSpecList(String value, Lst<Spectrum> speclist,
1084                               boolean isView) {
1085 
1086     String prefix = "1.";
1087     Lst<String> list;
1088     Lst<String> list0 = null;
1089     boolean isNone = (value.equalsIgnoreCase("NONE"));
1090     if (isNone || value.equalsIgnoreCase("all"))
1091       value = "*";
1092     if (value.indexOf("*") < 0) {
1093       // replace "3.1.1" with "3.1*1"
1094       String[] tokens = value.split(" ");
1095       SB sb = new SB();
1096       for (int i = 0; i < tokens.length; i++) {
1097         int pt = tokens[i].indexOf('.');
1098         if (pt != tokens[i].lastIndexOf('.'))
1099           tokens[i] = tokens[i].substring(0, pt + 1)
1100               + tokens[i].substring(pt + 1).replace('.', '_');
1101         sb.append(tokens[i]).append(" ");
1102       }
1103       value = sb.toString().trim();
1104     }
1105     if (value.equals("*")) {
1106       list = ScriptToken.getTokens(PanelNode
1107           .getSpectrumListAsString(panelNodes));
1108     } else if (value.startsWith("\"") || value.startsWith("'")) {
1109       list = ScriptToken.getTokens(value);
1110     } else {
1111       value = PT.rep(value, "_", " _ ");
1112       value = PT.rep(value, "-", " - ");
1113       list = ScriptToken.getTokens(value);
1114       list0 = ScriptToken.getTokens(PanelNode
1115           .getSpectrumListAsString(panelNodes));
1116       if (list0.size() == 0)
1117         return null;
1118     }
1119 
1120     String id0 = (isClosed() ? prefix : PanelNode.findNode(selectedPanel,
1121         panelNodes).id);
1122     id0 = id0.substring(0, id0.indexOf(".") + 1);
1123     SB sb = new SB();
1124     int n = list.size();
1125     String idLast = null;
1126     for (int i = 0; i < n; i++) {
1127       String id = list.get(i);
1128       double userYFactor = Double.NaN;
1129       int isubspec = -1;
1130       if (i + 1 < n && list.get(i + 1).equals("*")) {
1131         i += 2;
1132         userYFactor = Double.parseDouble(list.get(i));
1133       } else if (i + 1 < n && list.get(i + 1).equals("_")) {
1134         i += 2;
1135         isubspec = Integer.parseInt(list.get(i));
1136       }
1137       if (id.equals("-")) {
1138         if (idLast == null)
1139           idLast = list0.get(0);
1140         id = (i + 1 == n ? list0.get(list0.size() - 1) : list.get(++i));
1141         if (!id.contains("."))
1142           id = id0 + id;
1143         int pt = 0;
1144         while (pt < list0.size() && !list0.get(pt).equals(idLast))
1145           pt++;
1146         pt++;
1147         while (pt < list0.size() && !idLast.equals(id)) {
1148           PanelNode node = PanelNode.findNodeById((idLast = list0.get(pt++)),
1149               panelNodes);
1150           speclist.addLast(node.pd().getSpectrumAt(0));
1151           sb.append(",").append(idLast);
1152         }
1153         continue;
1154       }
1155       PanelNode node;
1156       if (id.startsWith("'") && id.endsWith("'"))
1157         id = "\"" + PT.trim(id, "'") + "\"";
1158       if (id.startsWith("\"")) {
1159         id = PT.trim(id, "\"");
1160         int pn = panelNodes.size();
1161         for (int j = 0; j < pn; j++) {
1162           node = panelNodes.get(j);
1163           if (node.fileName != null && node.fileName.startsWith(id)
1164               || node.frameTitle != null && node.frameTitle.startsWith(id)) {
1165             addSpecToList(node.pd(), userYFactor, -1, speclist, isView);
1166             sb.append(",").append(node.id);
1167           }
1168         }
1169         continue;
1170       }
1171       if (!id.contains("."))
1172         id = id0 + id;
1173       node = PanelNode.findNodeById(id, panelNodes);
1174       if (node == null)
1175         continue;
1176       idLast = id;
1177       addSpecToList(node.pd(), userYFactor, isubspec, speclist, isView);
1178       sb.append(",").append(id);
1179       if (isubspec > 0)
1180         sb.append(".").appendI(isubspec);
1181     }
1182     if (isView && speclist.size() > 0) {
1183       PanelNode node = PanelNode.findNodeById(sb.substring(1), panelNodes);
1184       if (node != null) {
1185         setNode(node); // was "fromTree true"
1186         // possibility of a problem here -- we are not communicating with Jmol
1187         // our model changes.
1188         speclist.clear();
1189       }
1190     }
1191     return (isNone ? "NONE" : sb.length() > 0 ? sb.toString().substring(1)
1192         : null);
1193   }
1194 
addSpecToList(PanelData pd, double userYFactor, int isubspec, Lst<Spectrum> list, boolean isView)1195   private void addSpecToList(PanelData pd, double userYFactor, int isubspec,
1196                              Lst<Spectrum> list, boolean isView) {
1197     if (isView) {
1198       Spectrum spec = pd.getSpectrumAt(0);
1199       spec.setUserYFactor(Double.isNaN(userYFactor) ? 1 : userYFactor);
1200       pd.addToList(isubspec - 1, list);
1201     } else {
1202       pd.selectFromEntireSet(isubspec - 1);
1203     }
1204   }
1205 
getSolutionColor(boolean asFitted)1206   public int getSolutionColor(boolean asFitted) {
1207     Spectrum spectrum = pd().getSpectrum();
1208     VisibleInterface vi = (spectrum.canShowSolutionColor() ? (VisibleInterface) JSViewer
1209         .getInterface("jspecview.common.Visible") : null);
1210     return (vi == null ? -1 : vi.getColour(spectrum, asFitted));
1211   }
1212 
openDataOrFile(Object data, String name, Lst<Spectrum> specs, String strUrl, int firstSpec, int lastSpec, boolean isAppend, String id)1213   public int openDataOrFile(Object data, String name, Lst<Spectrum> specs,
1214                             String strUrl, int firstSpec, int lastSpec,
1215                             boolean isAppend, String id) {
1216     if ("NONE".equals(name)) {
1217       close("View*");
1218       return FILE_OPEN_OK;
1219     }
1220     si.writeStatus("");
1221     String filePath = null;
1222     String newPath = null;
1223     String fileName = null;
1224     boolean isView = false;
1225     if (strUrl != null && strUrl.startsWith("cache://")) {
1226       /**
1227        * @j2sNative
1228        *
1229        *            data = Jmol.Cache.get(name = strUrl);
1230        *
1231        */
1232       {
1233       }
1234     }
1235     GenericFileInterface file = null;
1236     if (data != null) {
1237       try {
1238         fileName = name;
1239         newPath = filePath = JSVFileManager.getFullPathName(name);
1240       } catch (JSVException e) {
1241         // ok...
1242       }
1243     } else if (specs != null) {
1244       isView = true;
1245       newPath = fileName = filePath = "View" + (++nViews);
1246     } else if (strUrl != null) {
1247       try {
1248         file = apiPlatform.newFile(strUrl);
1249         // System.out.println("strURL=" + strUrl);
1250         // System.out.println("JSVFileManager.appletDocumentBase=" +
1251         // JSVFileManager.appletDocumentBase);
1252         URL u = new URL(JSVFileManager.appletDocumentBase, strUrl, null);
1253         // System.out.println("u=" + u);
1254         filePath = u.toString();
1255         recentURL = filePath;
1256         fileName = JSVFileManager.getTagName(filePath);
1257         // System.out.println("fileName=" + fileName);
1258       } catch (MalformedURLException e) {
1259         fileName = file.getName();
1260         newPath = filePath = file.getFullPath();
1261         recentURL = null;
1262       }
1263     }
1264     // if (!isView)
1265     int pt = -1;
1266     if ((pt = PanelNode.isOpen(panelNodes, filePath)) >= 0
1267         || (pt = PanelNode.isOpen(panelNodes, strUrl)) >= 0) {
1268       if (isView) {
1269         --nViews;
1270         setNode(panelNodes.get(pt)); // was fromTree true
1271       } else {
1272         si.writeStatus(filePath + " is already open");
1273       }
1274       return FILE_OPEN_ALREADY;
1275     }
1276     if (!isAppend && !isView)
1277       close("all"); // with CHECK we may still need to do this
1278     si.setCursor(GenericPlatform.CURSOR_WAIT);
1279     try {
1280       si.siSetCurrentSource(isView ? JDXSource.createView(specs) : JDXReader
1281           .createJDXSource(file, data, filePath,
1282               obscureTitleFromUser == Boolean.TRUE, loadImaginary, firstSpec,
1283               lastSpec, nmrMaxY));
1284 
1285     } catch (Exception e) {
1286       /**
1287        * @j2sNative alert(e.toString())
1288        */
1289       {
1290     	  e.printStackTrace();
1291         Logger.error(e.toString());
1292         if (Logger.debugging)
1293           e.printStackTrace();
1294         si.writeStatus(e.getMessage());
1295       }
1296       si.setCursor(GenericPlatform.CURSOR_DEFAULT);
1297       if (isApplet) {
1298         selectedPanel.showMessage(e.toString(), "Error Opening File");
1299       }
1300       return FILE_OPEN_ERROR;
1301     }
1302     si.setCursor(GenericPlatform.CURSOR_DEFAULT);
1303     System.gc();
1304     if (newPath == null) {
1305       newPath = currentSource.getFilePath();
1306       if (newPath != null)
1307         fileName = newPath.substring(newPath.lastIndexOf("/") + 1);
1308     } else {
1309       currentSource.setFilePath(newPath);
1310     }
1311     if (id == null && !isView)
1312       id = newPath;
1313     if (id != null)
1314       currentSource.setID(id);
1315     si.siSetLoaded(fileName, newPath);
1316 
1317     Spectrum spec = currentSource.getJDXSpectrum(0);
1318     if (spec == null) {
1319       return FILE_OPEN_NO_DATA;
1320     }
1321 
1322     specs = currentSource.getSpectra();
1323     Spectrum.process(specs, irMode);
1324 
1325     boolean autoOverlay = interfaceOverlaid
1326         || spec.isAutoOverlayFromJmolClick();
1327 
1328     boolean combine = isView || autoOverlay && currentSource.isCompoundSource;
1329     if (combine) {
1330       combineSpectra((isView ? strUrl : null));
1331     } else {
1332       splitSpectra();
1333     }
1334     pd().setTaintedAll();
1335     if (!isView)
1336       si.siUpdateRecentMenus(filePath);
1337     return FILE_OPEN_OK;
1338   }
1339 
close(String value)1340   public void close(String value) {
1341     // close * > 1 "close all except one spectrum."
1342     // close SIMULATIONS > 1 "close simulations until no more than one spectrum is present,
1343     // or all simulations if that is not possible."
1344     int n0 = 0;
1345     int pt = (value == null ? -2 : value.indexOf(">"));
1346     if (pt > 0) {
1347       n0 = PT.parseInt(value.substring(pt + 1).trim());
1348       value = value.substring(0, pt).trim();
1349     }
1350     if ("*".equals(value))
1351       value = "all";
1352     boolean isAll = (value == "all");
1353     if (value == null || n0 == 0 && value.equalsIgnoreCase("all")) {
1354       closeSource(null);
1355       return;
1356     }
1357     boolean isViews = value.equalsIgnoreCase("views");
1358     Lst<JDXSource> list = new Lst<JDXSource>();
1359     JDXSource source;
1360     value = value.replace('\\', '/');
1361     int n = panelNodes.size();
1362     int nMax = n - n0;
1363     if (value.endsWith("*")) {
1364       value = value.substring(0, value.length() - 1);
1365       for (int i = n; --i >= 0;)
1366         if (panelNodes.get(i).fileName.startsWith(value))
1367           list.addLast(panelNodes.get(i).source);
1368     } else if (value.equalsIgnoreCase("selected")) {
1369       JDXSource lastSource = null;
1370       for (int i = n; --i >= 0;) {
1371         source = panelNodes.get(i).source;
1372         if (panelNodes.get(i).isSelected
1373             && (lastSource == null || lastSource != source))
1374           list.addLast(source);
1375         lastSource = source;
1376       }
1377     } else if (isAll || isViews || value.equalsIgnoreCase("simulations")) {
1378       for (int n1 = 0, i = n; --i >= 0 && n1 < nMax;)
1379         if (isAll ? true : isViews ? panelNodes.get(i).isView : panelNodes
1380             .get(i).isSimulation) {
1381           list.addLast(panelNodes.get(i).source);
1382           n1++;
1383         }
1384     } else {
1385       source = (value.length() == 0 ? currentSource : PanelNode
1386           .findSourceByNameOrId(value, panelNodes));
1387       if (source != null)
1388         list.addLast(source);
1389     }
1390     for (int i = list.size(); --i >= 0;)
1391       closeSource(list.get(i));
1392     if (selectedPanel == null && panelNodes.size() > 0)
1393       si.siSetSelectedPanel(PanelNode.getLastFileFirstNode(panelNodes));
1394   }
1395 
execLoad(String value, String script)1396   public void execLoad(String value, String script) {
1397     JSVAppletObject applet = html5Applet;
1398     boolean isID = false;
1399     /**
1400      * When part of a view set, route all internal database requests through
1401      * this.html5Applet._search.
1402      *
1403      * @j2sNative
1404      *
1405      *            isID = (applet && applet._viewSet != null && !value.startsWith("ID"));
1406      *
1407      */
1408     if (isID) {
1409       // note that this was not functional, as it was missing {}
1410       applet._search(value);
1411       return;
1412     }
1413     // load   (alone) just runs defaultLoadScript
1414     // load ID "xx"...
1415     Lst<String> tokens = ScriptToken.getTokens(value);
1416     String filename = tokens.get(0);
1417     String id = null;
1418     int pt = 0;
1419     if (filename.equalsIgnoreCase("ID")) {
1420       id = PT.trimQuotes(tokens.get(1));
1421       filename = tokens.get(2);
1422       pt = 2;
1423     }
1424     boolean isAppend = filename.equalsIgnoreCase("APPEND");
1425     boolean isCheck = filename.equalsIgnoreCase("CHECK");
1426     if (isAppend || isCheck)
1427       pt++;
1428     if (pt > 0)
1429       filename = tokens.get(pt);
1430     if (script == null)
1431       script = defaultLoadScript;
1432     if (filename.equals("?")) {
1433       openFileFromDialog(isAppend, false, null, script);
1434       return;
1435     }
1436     if (filename.equals("http://?")) {
1437       openFileFromDialog(isAppend, true, null, null);
1438       return;
1439     }
1440     if (filename.equals("$?") || filename.equals("$H1?")) {
1441       openFileFromDialog(isAppend, true, "H1", null);
1442       return;
1443     }
1444     if (filename.equals("$C13?")) {
1445       openFileFromDialog(isAppend, true, "C13", null);
1446       return;
1447     }
1448     boolean isH1 = filename.equalsIgnoreCase("MOL")
1449         || filename.equalsIgnoreCase("H1");
1450     boolean isC13 = filename.equalsIgnoreCase("C13");
1451     if (isH1 || isC13)
1452       filename = JSVFileManager.SIMULATION_PROTOCOL + (isH1 ? "H1/" : "C13/")
1453           + "MOL=" + PT.trimQuotes(tokens.get(++pt));
1454     if (!isCheck && !isAppend) {
1455       if (filename.equals("\"\"") && currentSource != null)
1456         filename = currentSource.getFilePath();
1457       close("all");
1458     }
1459     filename = PT.trimQuotes(filename);
1460     boolean isSimulation = filename.startsWith("$");
1461     if (isSimulation) {
1462       if (!filename.startsWith("$H1") && !filename.startsWith("$C13"))
1463         filename = "$H1/" + filename.substring(1);
1464       filename = JSVFileManager.SIMULATION_PROTOCOL + filename.substring(1);
1465     }
1466     int firstSpec = (pt + 1 < tokens.size() ? Integer.valueOf(tokens.get(++pt))
1467         .intValue() : -1);
1468     int lastSpec = (pt + 1 < tokens.size() ? Integer.valueOf(tokens.get(++pt))
1469         .intValue() : firstSpec);
1470     si.siOpenDataOrFile(null, null, null, filename, firstSpec, lastSpec,
1471         isAppend, script, id);
1472     if (isSimulation) {
1473       close("views");
1474       execView("*", true);
1475     }
1476   }
1477 
combineSpectra(String name)1478   public void combineSpectra(String name) {
1479     JDXSource source = currentSource;
1480     Lst<Spectrum> specs = source.getSpectra();
1481     boolean haveSimulation = false;
1482     for (int i = specs.size(); --i >= 0;)
1483       if (specs.get(i).isSimulation) {
1484         haveSimulation = true;
1485         break;
1486       }
1487 
1488     JSVPanel jsvp = si.siGetNewJSVPanel2(specs);
1489     jsvp.setTitle(source.getTitle());
1490     if (jsvp.getTitle().equals("")) {
1491       jsvp.getPanelData().setViewTitle(source.getFilePath());
1492       jsvp.setTitle(name);
1493     }
1494     si.siSetPropertiesFromPreferences(jsvp, true);
1495     spectraTree.createTree(++fileCount, source, new JSVPanel[] { jsvp })
1496         .getPanelNode().isView = true;
1497     PanelNode node = PanelNode.findNode(selectedPanel, panelNodes);
1498     node.setFrameTitle(name);
1499     node.isView = true;
1500     if (autoShowLegend && pd().getNumberOfGraphSets() == 1)
1501       node.setLegend(getDialog(AType.OverlayLegend, null));
1502     si.siSetMenuEnables(node, false);
1503     if (haveSimulation)
1504       pd().splitStack(true);
1505   }
1506 
closeSource(JDXSource source)1507   public void closeSource(JDXSource source) {
1508     // Remove nodes and dispose of frames
1509     JSVTreeNode rootNode = spectraTree.getRootNode();
1510     String fileName = (source == null ? null : source.getFilePath());
1511     Lst<JSVTreeNode> toDelete = new Lst<JSVTreeNode>();
1512     Enumeration<?> enume = rootNode.children();
1513     while (enume.hasMoreElements()) {
1514       JSVTreeNode node = (JSVTreeNode) enume.nextElement();
1515       if (fileName == null
1516           || node.getPanelNode().source.matchesFilePath(fileName)) {
1517         Logger.info("Closing " + node.getPanelNode().source.getFilePath());
1518         for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
1519           JSVTreeNode childNode = (JSVTreeNode) e.nextElement();
1520           toDelete.addLast(childNode);
1521           panelNodes.removeObj(childNode.getPanelNode());
1522         }
1523         toDelete.addLast(node);
1524         if (fileName != null)
1525           break;
1526       }
1527     }
1528 
1529     spectraTree.deleteNodes(toDelete);
1530     if (source == null) {
1531       // jsvpPopupMenu.dispose();
1532       if (currentSource != null)
1533         currentSource.dispose();
1534       currentSource = null;
1535       // jsvpPopupMenu.dispose();
1536       if (selectedPanel != null)
1537         selectedPanel.dispose();
1538     } else {
1539       // setFrameAndTreeNode(panelNodes.size() - 1);
1540     }
1541 
1542     if (currentSource == source) {
1543       si.siSetSelectedPanel(null);
1544       si.siSetCurrentSource(null);
1545     }
1546 
1547     int max = 0;
1548     for (int i = 0; i < panelNodes.size(); i++) {
1549       float f = PT.parseFloat(panelNodes.get(i).id);
1550       if (f >= max + 1)
1551         max = (int) Math.floor(f);
1552     }
1553     fileCount = max;
1554     System.gc();
1555     if (Logger.debugging)
1556       Logger.checkMemory();
1557     si.siSourceClosed(source);
1558   }
1559 
setFrameAndTreeNode(int i)1560   public void setFrameAndTreeNode(int i) {
1561     if (panelNodes == null || i < 0 || i >= panelNodes.size())
1562       return;
1563     setNode(panelNodes.get(i));
1564   }
1565 
selectFrameNode(JSVPanel jsvp)1566   public PanelNode selectFrameNode(JSVPanel jsvp) {
1567     // Find Node in SpectraTree and select it
1568     PanelNode node = PanelNode.findNode(jsvp, panelNodes);
1569     if (node == null)
1570       return null;
1571     spectraTree.setPath(spectraTree.newTreePath(node.treeNode.getPath()));
1572     setOverlayLegendVisibility(null, false);
1573     return node;
1574   }
1575 
setSpectrum(String value)1576   private boolean setSpectrum(String value) {
1577     if (value.indexOf('.') >= 0) {
1578       PanelNode node = PanelNode.findNodeById(value, panelNodes);
1579       if (node == null)
1580         return false;
1581       setNode(node);
1582     } else {
1583       int n = PT.parseInt(value);
1584       if (n <= 0) {
1585         checkOverlay();
1586         return false;
1587       }
1588       setFrameAndTreeNode(n - 1);
1589     }
1590     return true;
1591   }
1592 
splitSpectra()1593   public void splitSpectra() {
1594     JDXSource source = currentSource;
1595     Lst<Spectrum> specs = source.getSpectra();
1596     JSVPanel[] panels = new JSVPanel[specs.size()];
1597     JSVPanel jsvp = null;
1598     for (int i = 0; i < specs.size(); i++) {
1599       Spectrum spec = specs.get(i);
1600       jsvp = si.siGetNewJSVPanel(spec);
1601       si.siSetPropertiesFromPreferences(jsvp, true);
1602       panels[i] = jsvp;
1603     }
1604     // arrange windows in ascending order
1605     spectraTree.createTree(++fileCount, source, panels);
1606     si.siGetNewJSVPanel(null); // end of operation
1607     PanelNode node = PanelNode.findNode(selectedPanel, panelNodes);
1608     si.siSetMenuEnables(node, true);
1609   }
1610 
selectedTreeNode(JSVTreeNode node)1611   public void selectedTreeNode(JSVTreeNode node) {
1612     if (node == null) {
1613       return;
1614     }
1615     if (node.isLeaf()) {
1616       setNode(node.getPanelNode());
1617     } else {
1618       System.out.println("not a leaf");
1619     }
1620     si.siSetCurrentSource(node.getPanelNode().source);
1621   }
1622 
dispose()1623   public void dispose() {
1624     fileHelper = null;
1625     if (viewDialog != null)
1626       viewDialog.dispose();
1627     viewDialog = null;
1628     if (overlayLegendDialog != null)
1629       overlayLegendDialog.dispose();
1630     overlayLegendDialog = null;
1631 
1632     if (jsvpPopupMenu != null) {
1633       jsvpPopupMenu.jpiDispose();
1634       jsvpPopupMenu = null;
1635     }
1636     if (panelNodes != null)
1637       for (int i = panelNodes.size(); --i >= 0;) {
1638         panelNodes.get(i).dispose();
1639         panelNodes.removeItemAt(i);
1640       }
1641   }
1642 
runScript(String script)1643   public void runScript(String script) {
1644     if (scriptQueue == null)
1645       si.siProcessCommand(script);
1646     else
1647       scriptQueue.addLast(script);
1648   }
1649 
requestRepaint()1650   public void requestRepaint() {
1651     if (selectedPanel != null)
1652       repaintManager.refresh();
1653   }
1654 
repaintDone()1655   public void repaintDone() {
1656     repaintManager.repaintDone();
1657   }
1658 
checkOverlay()1659   public void checkOverlay() {
1660     if (mainPanel != null)
1661       markSelectedPanels(panelNodes, mainPanel.getCurrentPanelIndex());
1662     viewDialog = getDialog(AType.Views, null);
1663   }
1664 
markSelectedPanels(Lst<PanelNode> panelNodes, int ip)1665   private void markSelectedPanels(Lst<PanelNode> panelNodes, int ip) {
1666     for (int i = panelNodes.size(); --i >= 0;)
1667       panelNodes.get(i).isSelected = (ip == i);
1668   }
1669 
1670   private int recentStackPercent = 5;
1671 
execOverlayOffsetY(int offset)1672   private void execOverlayOffsetY(int offset) {
1673     if (offset == Integer.MIN_VALUE) {
1674       if (selectedPanel == null)
1675         return;
1676       String soffset = selectedPanel.getInput(
1677           "Enter a vertical offset in percent for stacked plots", "Overlay", ""
1678               + recentStackPercent);
1679       float f = PT.parseFloat(soffset);
1680       if (Float.isNaN(f))
1681         return;
1682       offset = (int) f;
1683     }
1684     recentStackPercent = offset;
1685     parameters.viewOffset = offset;
1686     if (isClosed())
1687       pd().setYStackOffsetPercent(offset);
1688   }
1689 
execScriptInline(String script)1690   private void execScriptInline(String script) {
1691     if (script.length() > 0)
1692       script = script.substring(6).trim();
1693     if (script.length() == 0)
1694       script = selectedPanel.getInput("Enter a JSpecView script", "Script",
1695           recentScript);
1696     if (script == null)
1697       return;
1698     recentScript = script;
1699     runScriptNow(script);
1700   }
1701 
1702   // / called by JSmol JavaScript
1703 
setDisplay(Object canvas)1704   public void setDisplay(Object canvas) {
1705     // used by JSmol/HTML5 when a canvas is resized
1706     apiPlatform.setViewer(this, display = canvas);
1707     int[] wh = new int[2];
1708     apiPlatform.getFullScreenDimensions(canvas, wh);
1709     setScreenDimension(wh[0], wh[1]);
1710   }
1711 
setScreenDimension(int width, int height)1712   public void setScreenDimension(int width, int height) {
1713     // There is a bug in Netscape 4.7*+MacOS 9 when comparing dimension objects
1714     // so don't try dim1.equals(dim2)
1715     height = Math.min(height, maximumSize);
1716     width = Math.min(width, maximumSize);
1717     if (screenWidth == width && screenHeight == height)
1718       return;
1719     // System.out.println("HMM " + width + " " + height + " " + maximumSize);
1720     resizeImage(width, height);
1721   }
1722 
resizeImage(int width, int height)1723   void resizeImage(int width, int height) {
1724     if (width > 0) {
1725       screenWidth = width;
1726       screenHeight = height;
1727     } else {
1728       width = (screenWidth == 0 ? screenWidth = 500 : screenWidth);
1729       height = (screenHeight == 0 ? screenHeight = 500 : screenHeight);
1730     }
1731     g2d.setWindowParameters(width, height);
1732   }
1733 
1734   /**
1735    * for JavaScript only; this is the call to draw the spectrum
1736    *
1737    */
updateJS()1738   public void updateJS() {
1739     if (selectedPanel != null)
1740       selectedPanel.paintComponent(apiPlatform.getGraphics(null));
1741   }
1742 
1743   /**
1744    * called by JSmol.js mouse event
1745    *
1746    * @param id
1747    * @param x
1748    * @param y
1749    * @param modifiers
1750    * @param time
1751    * @return t/f
1752    */
processMouseEvent(int id, int x, int y, int modifiers, long time)1753   public boolean processMouseEvent(int id, int x, int y, int modifiers,
1754                                    long time) {
1755     return (selectedPanel != null && selectedPanel.processMouseEvent(id, x, y,
1756         modifiers, time));
1757   }
1758 
processTwoPointGesture(float[][][] touches)1759   public void processTwoPointGesture(float[][][] touches) {
1760     if (!isClosed())
1761       selectedPanel.processTwoPointGesture(touches);
1762   }
1763 
getApplet()1764   public JSVAppletObject getApplet() {
1765     return html5Applet;
1766   }
1767 
1768   /**
1769    * @param fileName
1770    * @param flags
1771    */
openFileAsyncSpecial(String fileName, int flags)1772   public void openFileAsyncSpecial(String fileName, int flags) {
1773     String ans = (currentSource == null ? "NO" : getDialogManager()
1774         .getDialogInput(this,
1775             "Do you want to append this file? (Answer NO to replace.)",
1776             "Drag/Drop Action", DialogManager.QUESTION_MESSAGE, null, null,
1777             "YES"));
1778     if (ans == null)
1779       return;
1780     String pre = (ans.toLowerCase().startsWith("y") ? "append" : "");
1781     String post = (pre == "" ? "" : "; view *");
1782     runScript("load " + pre + " \"" + fileName + "\"" + post);
1783   }
1784 
getHeight()1785   public int getHeight() {
1786     return screenHeight;
1787   }
1788 
getWidth()1789   public int getWidth() {
1790     return screenWidth;
1791   }
1792 
getPlatformInterface(String type)1793   public Object getPlatformInterface(String type) {
1794     return getInterface("jspecview." + (isJS ? "js2d.Js" : "java.Awt") + type);
1795   }
1796 
getDialogManager()1797   public DialogManager getDialogManager() {
1798     if (dialogManager != null)
1799       return dialogManager;
1800     dialogManager = (DialogManager) getPlatformInterface("DialogManager");
1801     //Interface.getInterface("jspecview.awtjs2d.JsDialogManager");
1802     return dialogManager.set(this);
1803   }
1804 
getDialog(AType type, Spectrum spec)1805   public JSVDialog getDialog(AType type, Spectrum spec) {
1806     String root = "jspecview.dialog.";
1807     switch (type) {
1808     case Integration:
1809       return ((JSVDialog) getInterface(root + "IntegrationDialog")).setParams(
1810           "Integration for " + spec, this, spec);
1811     case Measurements:
1812       return ((JSVDialog) getInterface(root + "MeasurementsDialog")).setParams(
1813           "Measurements for " + spec, this, spec);
1814     case PeakList:
1815       return ((JSVDialog) getInterface(root + "PeakListDialog")).setParams(
1816           "Peak List for " + spec, this, spec);
1817     case OverlayLegend:
1818       return overlayLegendDialog = ((JSVDialog) getInterface(root
1819           + "OverlayLegendDialog")).setParams(pd().getViewTitle(), this, null);
1820     case Views:
1821       return viewDialog = ((JSVDialog) getInterface(root + "ViewsDialog"))
1822           .setParams("View/Combine/Close Spectra", this, null);
1823     default:
1824       return null;
1825     }
1826   }
1827 
show(String what)1828   private void show(String what) {
1829     getDialogManager();
1830     if (what.equals("properties")) {
1831       dialogManager.showProperties(null, pd().getSpectrum());
1832     } else if (what.equals("errors")) {
1833       dialogManager.showSourceErrors(null, currentSource);
1834     } else if (what.equals("source")) {
1835       if (currentSource == null) {
1836         if (panelNodes.size() > 0)
1837           dialogManager.showMessageDialog(null, "Please Select a Spectrum",
1838               "Select Spectrum", DialogManager.ERROR_MESSAGE);
1839         return;
1840       }
1841       dialogManager.showSource(this, pd().getSpectrum());
1842     } else if (what.startsWith("solutioncolorfill")) {
1843       if (what.indexOf("all") >= 0) {
1844         for (int i = panelNodes.size(); --i >= 0;)
1845           panelNodes.get(i).pd().setSolutionColor(what);
1846       } else {
1847         pd().setSolutionColor(what);
1848       }
1849     } else if (what.startsWith("solutioncolor")) {
1850       String msg = getSolutionColorStr(what.indexOf("false") < 0);
1851       msg = "background-color:rgb(" + msg
1852           + ")'><br />Predicted Solution Colour- RGB(" + msg + ")<br /><br />";
1853       if (isJS) {
1854         dialogManager.showMessage(this, "<div style='width:100%;height:100%;"
1855             + msg + "</div>", "Predicted Colour");
1856       } else {
1857         selectedPanel.showMessage("<html><body style='" + msg
1858             + "</body></html>", "Predicted Colour");
1859       }
1860     }
1861   }
1862 
1863   private PrintLayout lastPrintLayout;
1864   private Object offWindowFrame;
1865 
getDialogPrint(boolean isJob)1866   public PrintLayout getDialogPrint(boolean isJob) {
1867     if (!isJS)
1868       try {
1869         PrintLayout pl = ((JSVPrintDialog) getPlatformInterface("PrintDialog"))
1870             .set(offWindowFrame, lastPrintLayout, isJob).getPrintLayout();
1871         if (pl != null)
1872           lastPrintLayout = pl;
1873         return pl;
1874       } catch (Exception e) {
1875       }
1876     return new PrintLayout(pd());
1877   }
1878 
setIRmode(String mode)1879   public void setIRmode(String mode) {
1880     if (mode.equals("AtoT")) {
1881       irMode = IRMode.TO_TRANS;
1882     } else if (mode.equals("TtoA")) {
1883       irMode = IRMode.TO_ABS;
1884     } else {
1885       irMode = IRMode.getMode(mode);
1886     }
1887   }
1888 
getOptionFromDialog(String[] items, String title, String label)1889   public int getOptionFromDialog(String[] items, String title, String label) {
1890     return getDialogManager().getOptionFromDialog(null, items, selectedPanel,
1891         title, label);
1892   }
1893 
print(String fileName)1894   public String print(String fileName) {
1895     return execWrite("PDF \"" + fileName + "\"");
1896   }
1897 
execWrite(String value)1898   private String execWrite(String value) {
1899     if (isJS && value == null)
1900       value = "PDF";
1901     String msg = ((ExportInterface) JSViewer
1902         .getInterface("jspecview.export.Exporter")).write(this,
1903         value == null ? null : ScriptToken.getTokens(value), false);
1904     si.writeStatus(msg);
1905     return msg;
1906   }
1907 
export(String type, int n)1908   public String export(String type, int n) {
1909     if (type == null)
1910       type = "XY";
1911     PanelData pd = pd();
1912     int nMax = pd.getNumberOfSpectraInCurrentSet();
1913     if (n < -1 || n >= nMax)
1914       return "Maximum spectrum index (0-based) is " + (nMax - 1) + ".";
1915     Spectrum spec = (n < 0 ? pd.getSpectrum() : pd.getSpectrumAt(n));
1916     try {
1917       return ((ExportInterface) JSViewer
1918           .getInterface("jspecview.export.Exporter")).exportTheSpectrum(this,
1919           ExportType.getType(type), null, spec, 0,
1920           spec.getXYCoords().length - 1, null, type.equalsIgnoreCase("PDF"));
1921     } catch (Exception e) {
1922       Logger.error(e.toString());
1923       return null;
1924     }
1925   }
1926 
1927   @Override
postByteArray(String fileName, byte[] bytes)1928   public String postByteArray(String fileName, byte[] bytes) {
1929     return JSVFileManager.postByteArray(fileName, bytes);
1930   }
1931 
1932   @SuppressWarnings("resource")
getOutputChannel(String fileName, boolean isBinary)1933   public OC getOutputChannel(String fileName, boolean isBinary)
1934       throws Exception {
1935     OutputStream os = null;
1936     /**
1937      * in JavaScript, this will be a string buffer or byte array
1938      *
1939      * @j2sNative
1940      *
1941      *            while (fileName.startsWith("/")) fileName =
1942      *            fileName.substring(1);
1943      *
1944      *
1945      */
1946     {
1947       os = (fileName == null || fileName.equals(";base64,") ? null
1948           : new FileOutputStream(fileName));
1949     }
1950     return new OC().setParams(this, fileName, !isBinary, os);
1951   }
1952 
getInterface(String name)1953   public static Object getInterface(String name) {
1954     try {
1955       Class<?> x = Class.forName(name);
1956       return (x == null ? null : x.newInstance());
1957     } catch (Exception e) {
1958       Logger.error("Interface.java Error creating instance for " + name
1959           + ": \n" + e);
1960       return null;
1961     }
1962   }
1963 
showMessage(String msg)1964   public void showMessage(String msg) {
1965     if (selectedPanel != null && msg != null)
1966       selectedPanel.showMessage(msg, null);
1967   }
1968 
openFileFromDialog(boolean isAppend, boolean isURL, String simulationType, String script)1969   public void openFileFromDialog(boolean isAppend, boolean isURL,
1970                                  String simulationType, String script) {
1971     String url = null;
1972     if (simulationType != null) {
1973       url = fileHelper.getUrlFromDialog(
1974           "Enter the name or identifier of a compound", recentSimulation);
1975       if (url == null)
1976         return;
1977       recentSimulation = url;
1978       url = "$" + simulationType + "/" + url;
1979     } else if (isURL) {
1980       url = fileHelper.getUrlFromDialog("Enter the URL of a JCAMP-DX File",
1981           recentURL == null ? recentOpenURL : recentURL);
1982       if (url == null)
1983         return;
1984       recentOpenURL = url;
1985     } else {
1986       Object[] userData = new Object[] { Boolean.valueOf(isAppend), script };
1987       GenericFileInterface file = fileHelper.showFileOpenDialog(mainPanel,
1988           userData);
1989       // note that in JavaScript this will be asynchronous and file will be null.
1990       if (file != null)
1991         url = file.getFullPath();
1992       // it is not necessary to run the script in Java; we are not loading asynchronously
1993     }
1994     if (url != null)
1995       runScriptNow("load " + (isAppend ? "APPEND " : "") + "\"" + url + "\""
1996           + (script == null ? "" : ";" + script));
1997   }
1998 
1999   private String recentOpenURL = "http://";
2000   private String recentURL;
2001   private String recentSimulation = "tylenol";
2002 
2003   /**
2004    * Opens and displays a file
2005    *
2006    * @param fileName
2007    * @param closeFirst
2008    *
2009    */
openFile(String fileName, boolean closeFirst)2010   public void openFile(String fileName, boolean closeFirst) {
2011     if (closeFirst && panelNodes != null) {
2012       JDXSource source = PanelNode.findSourceByNameOrId(
2013           (new File(fileName)).getAbsolutePath(), panelNodes);
2014       if (source != null)
2015         closeSource(source);
2016     }
2017     si.siOpenDataOrFile(null, null, null, fileName, -1, -1, true,
2018         defaultLoadScript, null);
2019 
2020   }
2021 
selectPanel(JSVPanel jsvp, Lst<PanelNode> panelNodes)2022   public int selectPanel(JSVPanel jsvp, Lst<PanelNode> panelNodes) {
2023     int iPanel = -1;
2024     if (panelNodes != null) {
2025       for (int i = panelNodes.size(); --i >= 0;) {
2026         JSVPanel j = panelNodes.get(i).jsvp;
2027         if (j == jsvp) {
2028           iPanel = i;
2029         } else {
2030           j.setEnabled(false);
2031           j.setFocusable(false);
2032           j.getPanelData().closeAllDialogsExcept(AType.NONE);
2033         }
2034       }
2035       markSelectedPanels(panelNodes, iPanel);
2036     }
2037     return iPanel;
2038   }
2039 
checkAutoIntegrate()2040   public void checkAutoIntegrate() {
2041     if (autoIntegrate)
2042       pd().integrateAll(parameters);
2043   }
2044 
2045   /**
2046    * Parses the JavaScript call parameters and executes them accordingly
2047    *
2048    * @param params
2049    *        String
2050    */
parseInitScript(String params)2051   public void parseInitScript(String params) {
2052     if (params == null)
2053       params = "";
2054     ScriptTokenizer allParamTokens = new ScriptTokenizer(params, true);
2055     if (Logger.debugging) {
2056       Logger.info("Running in DEBUG mode");
2057     }
2058     while (allParamTokens.hasMoreTokens()) {
2059       String token = allParamTokens.nextToken();
2060       // now split the key/value pair
2061       ScriptTokenizer eachParam = new ScriptTokenizer(token, false);
2062       String key = eachParam.nextToken();
2063       if (key.equalsIgnoreCase("SET"))
2064         key = eachParam.nextToken();
2065       key = key.toUpperCase();
2066       ScriptToken st = ScriptToken.getScriptToken(key);
2067       String value = ScriptToken.getValue(st, eachParam, token);
2068       //if (Logger.debugging)
2069       Logger.info("KEY-> " + key + " VALUE-> " + value + " : " + st);
2070       try {
2071         switch (st) {
2072         default:
2073           parameters.set(null, st, value);
2074           break;
2075         case UNKNOWN:
2076           break;
2077         case APPLETID:
2078           fullName = appletName + "__" + (appletName = value) + "__";
2079           JSVAppletObject applet = null;
2080           /**
2081            * @j2sNative
2082            *
2083            *            self.Jmol && (applet = Jmol._applets[value]);
2084            *
2085            *
2086            */
2087           {
2088           }
2089           this.html5Applet = applet;
2090           break;
2091         case AUTOINTEGRATE:
2092           autoIntegrate = Parameters.isTrue(value);
2093           break;
2094         case COMPOUNDMENUON:
2095           // not implemented          allowCompoundMenu = Boolean.parseBoolean(value);
2096           break;
2097         case APPLETREADYCALLBACKFUNCTIONNAME:
2098         case COORDCALLBACKFUNCTIONNAME:
2099         case LOADFILECALLBACKFUNCTIONNAME:
2100         case PEAKCALLBACKFUNCTIONNAME:
2101         case SYNCCALLBACKFUNCTIONNAME:
2102           si.siExecSetCallback(st, value);
2103           break;
2104         case ENDINDEX:
2105           initialEndIndex = Integer.parseInt(value);
2106           break;
2107         case INTERFACE:
2108           checkOvelayInterface(value);
2109           break;
2110         case IRMODE:
2111           setIRmode(value);
2112           break;
2113         case MENUON:
2114           allowMenu = Boolean.parseBoolean(value);
2115           break;
2116         case OBSCURE:
2117           if (obscureTitleFromUser == null) // once only
2118             obscureTitleFromUser = Boolean.valueOf(value);
2119           break;
2120         case STARTINDEX:
2121           initialStartIndex = Integer.parseInt(value);
2122           break;
2123         // case SPECTRUMNUMBER:
2124         // initialSpectrumNumber = Integer.parseInt(value);
2125         // break;
2126         case SYNCID:
2127           fullName = appletName + "__" + (syncID = value) + "__";
2128           break;
2129         }
2130       } catch (Exception e) {
2131       }
2132     }
2133   }
2134 
getSolutionColorStr(boolean asFit)2135   public String getSolutionColorStr(boolean asFit) {
2136     P3 pt = CU.colorPtFromInt(getSolutionColor(asFit), null);
2137     return (int) pt.x + "," + (int) pt.y + "," + (int) pt.z;
2138   }
2139 
checkCommandLineForTip(char c, String cmd, boolean oneLineOnly)2140   public String checkCommandLineForTip(char c, String cmd, boolean oneLineOnly) {
2141     boolean isHelp = (c == '\1');
2142     if (!isHelp && c != '\0') {
2143       if (c != '\t' && (c == '\n' || c < 32 || c > 126))
2144         return null;
2145       cmd += (Character.isISOControl(c) ? "" : "" + c);
2146     }
2147     String tip;
2148     if (cmd.indexOf(";") >= 0)
2149       cmd = cmd.substring(cmd.lastIndexOf(";") + 1);
2150     String ret = null;
2151     while (cmd.startsWith(" "))
2152       cmd = cmd.substring(1);
2153     if (cmd.length() == 0 && !isHelp) {
2154       tip = "";
2155     } else {
2156       Lst<String> tokens = ScriptToken.getTokens(cmd);
2157       if (tokens.size() == 0 && !isHelp)
2158         return "";
2159       boolean isExact = (cmd.endsWith(" ") || tokens.size() > 1 && oneLineOnly);
2160       Lst<ScriptToken> list = ScriptToken.getScriptTokenList(
2161           tokens.size() == 0 ? null : tokens.get(0), isExact);// || isHelp && tokens.size() > 0);
2162       switch (list.size()) {
2163       case 0:
2164         tip = "?";
2165         break;
2166       case 1:
2167         ScriptToken st = list.get(0);
2168         tip = st.getTip();
2169         try {
2170           if (tip.indexOf("TRUE") >= 0)
2171             tip = " (" + parameters.getBoolean(st) + ")";
2172           else if (st.name().indexOf("COLOR") >= 0)
2173             tip = " (" + CU.toRGBHexString(parameters.getElementColor(st))
2174                 + ")";
2175           else
2176             tip = "";
2177         } catch (Exception e) {
2178           return null;
2179         }
2180         if (c == '\t' || isExact || !oneLineOnly) {
2181           tip = st.name() + " " + st.getTip() + tip + " " + st.getDescription();
2182           if (c == '\t')
2183             ret = st.name() + " ";
2184           break;
2185         }
2186         tip = st.name() + " " + tip;
2187         break;
2188       default:
2189         tip = ScriptToken.getNameList(list);
2190       }
2191     }
2192     if (oneLineOnly) {
2193       si.writeStatus(tip);
2194     } else {
2195       ret = tip;
2196     }
2197     return ret;
2198   }
2199 
checkScript(String script)2200   public String checkScript(String script) {
2201     return checkCommandLineForTip('\0', script, false);
2202   }
2203 
execHelp(String value)2204   private void execHelp(String value) {
2205     String s = checkCommandLineForTip('\1', value, false);
2206     if (s.indexOf(" ") < 0 && s.indexOf(",") > 0) {
2207       String[] tokens = PT.split(s, ",");
2208       Arrays.sort(tokens);
2209       s = "";
2210       for (int i = 0; i < tokens.length; i++) {
2211         ScriptToken st = ScriptToken.getScriptToken(tokens[i]);
2212         s += tokens[i] + " " + st.getTip() + "\n  " + st.getDescription()
2213             + "\n\n";
2214       }
2215       getDialogManager().showMessage(null, s, "HELP " + value);
2216     } else {
2217       selectedPanel.showMessage(s, "Help " + value);
2218     }
2219     System.out.println(s);
2220   }
2221 
2222 }
2223