formatting
[jalview.git] / src / jalview / bin / JalviewLite.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)\r
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle\r
4  * \r
5  * This file is part of Jalview.\r
6  * \r
7  * Jalview is free software: you can redistribute it and/or\r
8  * modify it under the terms of the GNU General Public License \r
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\r
10  * \r
11  * Jalview is distributed in the hope that it will be useful, but \r
12  * WITHOUT ANY WARRANTY; without even the implied warranty \r
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
14  * PURPOSE.  See the GNU General Public License for more details.\r
15  * \r
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.\r
17  */\r
18 package jalview.bin;\r
19 \r
20 import jalview.api.StructureSelectionManagerProvider;\r
21 import jalview.appletgui.AlignFrame;\r
22 import jalview.appletgui.AlignViewport;\r
23 import jalview.appletgui.EmbmenuFrame;\r
24 import jalview.appletgui.FeatureSettings;\r
25 import jalview.datamodel.Alignment;\r
26 import jalview.datamodel.AlignmentI;\r
27 import jalview.datamodel.AlignmentOrder;\r
28 import jalview.datamodel.ColumnSelection;\r
29 import jalview.datamodel.PDBEntry;\r
30 import jalview.datamodel.Sequence;\r
31 import jalview.datamodel.SequenceGroup;\r
32 import jalview.datamodel.SequenceI;\r
33 import jalview.io.AnnotationFile;\r
34 import jalview.io.AppletFormatAdapter;\r
35 import jalview.io.FileParse;\r
36 import jalview.io.IdentifyFile;\r
37 import jalview.io.JnetAnnotationMaker;\r
38 import jalview.javascript.JSFunctionExec;\r
39 import jalview.javascript.JalviewLiteJsApi;\r
40 import jalview.javascript.JsCallBack;\r
41 import jalview.structure.SelectionListener;\r
42 import jalview.structure.StructureSelectionManager;\r
43 \r
44 import java.applet.Applet;\r
45 import java.awt.Button;\r
46 import java.awt.Color;\r
47 import java.awt.Component;\r
48 import java.awt.EventQueue;\r
49 import java.awt.Font;\r
50 import java.awt.Frame;\r
51 import java.awt.Graphics;\r
52 import java.awt.event.ActionEvent;\r
53 import java.awt.event.WindowAdapter;\r
54 import java.awt.event.WindowEvent;\r
55 import java.io.BufferedReader;\r
56 import java.io.InputStreamReader;\r
57 import java.net.URL;\r
58 import java.util.Hashtable;\r
59 import java.util.StringTokenizer;\r
60 import java.util.Vector;\r
61 \r
62 import netscape.javascript.JSObject;\r
63 \r
64 /**\r
65  * Jalview Applet. Runs in Java 1.18 runtime\r
66  * \r
67  * @author $author$\r
68  * @version $Revision: 1.92 $\r
69  */\r
70 public class JalviewLite extends Applet implements\r
71         StructureSelectionManagerProvider, JalviewLiteJsApi\r
72 {\r
73 \r
74   public StructureSelectionManager getStructureSelectionManager()\r
75   {\r
76     return StructureSelectionManager.getStructureSelectionManager(this);\r
77   }\r
78 \r
79   // /////////////////////////////////////////\r
80   // The following public methods maybe called\r
81   // externally, eg via javascript in HTML page\r
82   /*\r
83    * (non-Javadoc)\r
84    * \r
85    * @see jalview.bin.JalviewLiteJsApi#getSelectedSequences()\r
86    */\r
87   public String getSelectedSequences()\r
88   {\r
89     return getSelectedSequencesFrom(getDefaultTargetFrame());\r
90   }\r
91 \r
92   /*\r
93    * (non-Javadoc)\r
94    * \r
95    * @see jalview.bin.JalviewLiteJsApi#getSelectedSequences(java.lang.String)\r
96    */\r
97   public String getSelectedSequences(String sep)\r
98   {\r
99     return getSelectedSequencesFrom(getDefaultTargetFrame(), sep);\r
100   }\r
101 \r
102   /*\r
103    * (non-Javadoc)\r
104    * \r
105    * @see\r
106    * jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui\r
107    * .AlignFrame)\r
108    */\r
109   public String getSelectedSequencesFrom(AlignFrame alf)\r
110   {\r
111     return getSelectedSequencesFrom(alf, separator); // ""+0x00AC);\r
112   }\r
113 \r
114   /*\r
115    * (non-Javadoc)\r
116    * \r
117    * @see\r
118    * jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui\r
119    * .AlignFrame, java.lang.String)\r
120    */\r
121   public String getSelectedSequencesFrom(AlignFrame alf, String sep)\r
122   {\r
123     StringBuffer result = new StringBuffer("");\r
124     if (sep == null || sep.length() == 0)\r
125     {\r
126       sep = separator; // "+0x00AC;\r
127     }\r
128     if (alf.viewport.getSelectionGroup() != null)\r
129     {\r
130       SequenceI[] seqs = alf.viewport.getSelectionGroup()\r
131               .getSequencesInOrder(alf.viewport.getAlignment());\r
132 \r
133       for (int i = 0; i < seqs.length; i++)\r
134       {\r
135         result.append(seqs[i].getName());\r
136         result.append(sep);\r
137       }\r
138     }\r
139 \r
140     return result.toString();\r
141   }\r
142 \r
143   /*\r
144    * (non-Javadoc)\r
145    * \r
146    * @see jalview.bin.JalviewLiteJsApi#highlight(java.lang.String,\r
147    * java.lang.String, java.lang.String)\r
148    */\r
149   public void highlight(String sequenceId, String position,\r
150           String alignedPosition)\r
151   {\r
152     highlightIn(getDefaultTargetFrame(), sequenceId, position,\r
153             alignedPosition);\r
154   }\r
155 \r
156   /*\r
157    * (non-Javadoc)\r
158    * \r
159    * @see jalview.bin.JalviewLiteJsApi#highlightIn(jalview.appletgui.AlignFrame,\r
160    * java.lang.String, java.lang.String, java.lang.String)\r
161    */\r
162   public void highlightIn(final AlignFrame alf, final String sequenceId,\r
163           final String position, final String alignedPosition)\r
164   {\r
165     // TODO: could try to highlight in all alignments if alf==null\r
166     jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(\r
167             alf.viewport.getAlignment().getSequencesArray());\r
168     final SequenceI sq = matcher.findIdMatch(sequenceId);\r
169     if (sq != null)\r
170     {\r
171       int apos = -1;\r
172       try\r
173       {\r
174         apos = new Integer(position).intValue();\r
175         apos--;\r
176       } catch (NumberFormatException ex)\r
177       {\r
178         return;\r
179       }\r
180       final StructureSelectionManagerProvider me = this;\r
181       final int pos = apos;\r
182       // use vamsas listener to broadcast to all listeners in scope\r
183       if (alignedPosition != null\r
184               && (alignedPosition.trim().length() == 0 || alignedPosition\r
185                       .toLowerCase().indexOf("false") > -1))\r
186       {\r
187         java.awt.EventQueue.invokeLater(new Runnable()\r
188         {\r
189           @Override\r
190           public void run()\r
191           {\r
192             StructureSelectionManager.getStructureSelectionManager(me)\r
193                     .mouseOverVamsasSequence(sq, sq.findIndex(pos), null);\r
194           }\r
195         });\r
196       }\r
197       else\r
198       {\r
199         java.awt.EventQueue.invokeLater(new Runnable()\r
200         {\r
201           @Override\r
202           public void run()\r
203           {\r
204             StructureSelectionManager.getStructureSelectionManager(me)\r
205                     .mouseOverVamsasSequence(sq, pos, null);\r
206           }\r
207         });\r
208       }\r
209     }\r
210   }\r
211 \r
212   /*\r
213    * (non-Javadoc)\r
214    * \r
215    * @see jalview.bin.JalviewLiteJsApi#select(java.lang.String,\r
216    * java.lang.String)\r
217    */\r
218   public void select(String sequenceIds, String columns)\r
219   {\r
220     selectIn(getDefaultTargetFrame(), sequenceIds, columns, separator);\r
221   }\r
222 \r
223   /*\r
224    * (non-Javadoc)\r
225    * \r
226    * @see jalview.bin.JalviewLiteJsApi#select(java.lang.String,\r
227    * java.lang.String, java.lang.String)\r
228    */\r
229   public void select(String sequenceIds, String columns, String sep)\r
230   {\r
231     selectIn(getDefaultTargetFrame(), sequenceIds, columns, sep);\r
232   }\r
233 \r
234   /*\r
235    * (non-Javadoc)\r
236    * \r
237    * @see jalview.bin.JalviewLiteJsApi#selectIn(jalview.appletgui.AlignFrame,\r
238    * java.lang.String, java.lang.String)\r
239    */\r
240   public void selectIn(AlignFrame alf, String sequenceIds, String columns)\r
241   {\r
242     selectIn(alf, sequenceIds, columns, separator);\r
243   }\r
244 \r
245   /*\r
246    * (non-Javadoc)\r
247    * \r
248    * @see jalview.bin.JalviewLiteJsApi#selectIn(jalview.appletgui.AlignFrame,\r
249    * java.lang.String, java.lang.String, java.lang.String)\r
250    */\r
251   public void selectIn(final AlignFrame alf, String sequenceIds,\r
252           String columns, String sep)\r
253   {\r
254     if (sep == null || sep.length() == 0)\r
255     {\r
256       sep = separator;\r
257     }\r
258     else\r
259     {\r
260       if (debug)\r
261       {\r
262         System.err.println("Selecting region using separator string '"\r
263                 + separator + "'");\r
264       }\r
265     }\r
266     // deparse fields\r
267     String[] ids = separatorListToArray(sequenceIds, sep);\r
268     String[] cols = separatorListToArray(columns, sep);\r
269     final SequenceGroup sel = new SequenceGroup();\r
270     final ColumnSelection csel = new ColumnSelection();\r
271     AlignmentI al = alf.viewport.getAlignment();\r
272     jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(\r
273             alf.viewport.getAlignment().getSequencesArray());\r
274     int start = 0, end = al.getWidth(), alw = al.getWidth();\r
275     boolean seqsfound = true;\r
276     if (ids != null && ids.length > 0)\r
277     {\r
278       seqsfound = false;\r
279       for (int i = 0; i < ids.length; i++)\r
280       {\r
281         if (ids[i].trim().length() == 0)\r
282         {\r
283           continue;\r
284         }\r
285         SequenceI sq = matcher.findIdMatch(ids[i]);\r
286         if (sq != null)\r
287         {\r
288           seqsfound = true;\r
289           sel.addSequence(sq, false);\r
290         }\r
291       }\r
292     }\r
293     boolean inseqpos = false;\r
294     if (cols != null && cols.length > 0)\r
295     {\r
296       boolean seset = false;\r
297       for (int i = 0; i < cols.length; i++)\r
298       {\r
299         String cl = cols[i].trim();\r
300         if (cl.length() == 0)\r
301         {\r
302           continue;\r
303         }\r
304         int p;\r
305         if ((p = cl.indexOf("-")) > -1)\r
306         {\r
307           int from = -1, to = -1;\r
308           try\r
309           {\r
310             from = new Integer(cl.substring(0, p)).intValue();\r
311             from--;\r
312           } catch (NumberFormatException ex)\r
313           {\r
314             System.err\r
315                     .println("ERROR: Couldn't parse first integer in range element column selection string '"\r
316                             + cl + "' - format is 'from-to'");\r
317             return;\r
318           }\r
319           try\r
320           {\r
321             to = new Integer(cl.substring(p + 1)).intValue();\r
322             to--;\r
323           } catch (NumberFormatException ex)\r
324           {\r
325             System.err\r
326                     .println("ERROR: Couldn't parse second integer in range element column selection string '"\r
327                             + cl + "' - format is 'from-to'");\r
328             return;\r
329           }\r
330           if (from >= 0 && to >= 0)\r
331           {\r
332             // valid range\r
333             if (from < to)\r
334             {\r
335               int t = to;\r
336               to = from;\r
337               to = t;\r
338             }\r
339             if (!seset)\r
340             {\r
341               start = from;\r
342               end = to;\r
343               seset = true;\r
344             }\r
345             else\r
346             {\r
347               // comment to prevent range extension\r
348               if (start > from)\r
349               {\r
350                 start = from;\r
351               }\r
352               if (end < to)\r
353               {\r
354                 end = to;\r
355               }\r
356             }\r
357             for (int r = from; r <= to; r++)\r
358             {\r
359               if (r >= 0 && r < alw)\r
360               {\r
361                 csel.addElement(r);\r
362               }\r
363             }\r
364             if (debug)\r
365             {\r
366               System.err.println("Range '" + cl + "' deparsed as [" + from\r
367                       + "," + to + "]");\r
368             }\r
369           }\r
370           else\r
371           {\r
372             System.err.println("ERROR: Invalid Range '" + cl\r
373                     + "' deparsed as [" + from + "," + to + "]");\r
374           }\r
375         }\r
376         else\r
377         {\r
378           int r = -1;\r
379           try\r
380           {\r
381             r = new Integer(cl).intValue();\r
382             r--;\r
383           } catch (NumberFormatException ex)\r
384           {\r
385             if (cl.toLowerCase().equals("sequence"))\r
386             {\r
387               // we are in the dataset sequence's coordinate frame.\r
388               inseqpos = true;\r
389             }\r
390             else\r
391             {\r
392               System.err\r
393                       .println("ERROR: Couldn't parse integer from point selection element of column selection string '"\r
394                               + cl + "'");\r
395               return;\r
396             }\r
397           }\r
398           if (r >= 0 && r <= alw)\r
399           {\r
400             if (!seset)\r
401             {\r
402               start = r;\r
403               end = r;\r
404               seset = true;\r
405             }\r
406             else\r
407             {\r
408               // comment to prevent range extension\r
409               if (start > r)\r
410               {\r
411                 start = r;\r
412               }\r
413               if (end < r)\r
414               {\r
415                 end = r;\r
416               }\r
417             }\r
418             csel.addElement(r);\r
419             if (debug)\r
420             {\r
421               System.err.println("Point selection '" + cl\r
422                       + "' deparsed as [" + r + "]");\r
423             }\r
424           }\r
425           else\r
426           {\r
427             System.err.println("ERROR: Invalid Point selection '" + cl\r
428                     + "' deparsed as [" + r + "]");\r
429           }\r
430         }\r
431       }\r
432     }\r
433     if (seqsfound)\r
434     {\r
435       // we only propagate the selection when it was the null selection, or the\r
436       // given sequences were found in the alignment.\r
437       if (inseqpos && sel.getSize() > 0)\r
438       {\r
439         // assume first sequence provides reference frame ?\r
440         SequenceI rs = sel.getSequenceAt(0);\r
441         start = rs.findIndex(start);\r
442         end = rs.findIndex(end);\r
443         if (csel != null)\r
444         {\r
445           Vector cs = csel.getSelected();\r
446           csel.clear();\r
447           for (int csi = 0, csiS = cs.size(); csi < csiS; csi++)\r
448           {\r
449             csel.addElement(rs.findIndex(((Integer) cs.elementAt(csi))\r
450                     .intValue()));\r
451           }\r
452         }\r
453       }\r
454       sel.setStartRes(start);\r
455       sel.setEndRes(end);\r
456       EventQueue.invokeLater(new Runnable()\r
457       {\r
458         @Override\r
459         public void run()\r
460         {\r
461           alf.select(sel, csel);\r
462         }\r
463       });\r
464     }\r
465   }\r
466 \r
467   /*\r
468    * (non-Javadoc)\r
469    * \r
470    * @see\r
471    * jalview.bin.JalviewLiteJsApi#getSelectedSequencesAsAlignment(java.lang.\r
472    * String, java.lang.String)\r
473    */\r
474   public String getSelectedSequencesAsAlignment(String format, String suffix)\r
475   {\r
476     return getSelectedSequencesAsAlignmentFrom(getDefaultTargetFrame(),\r
477             format, suffix);\r
478   }\r
479 \r
480   /*\r
481    * (non-Javadoc)\r
482    * \r
483    * @see\r
484    * jalview.bin.JalviewLiteJsApi#getSelectedSequencesAsAlignmentFrom(jalview\r
485    * .appletgui.AlignFrame, java.lang.String, java.lang.String)\r
486    */\r
487   public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,\r
488           String format, String suffix)\r
489   {\r
490     try\r
491     {\r
492       boolean seqlimits = suffix.equalsIgnoreCase("true");\r
493       if (alf.viewport.getSelectionGroup() != null)\r
494       {\r
495         // JBPNote: getSelectionAsNewSequence behaviour has changed - this\r
496         // method now returns a full copy of sequence data\r
497         // TODO consider using getSequenceSelection instead here\r
498         String reply = new AppletFormatAdapter().formatSequences(format,\r
499                 new Alignment(alf.viewport.getSelectionAsNewSequence()),\r
500                 seqlimits);\r
501         return reply;\r
502       }\r
503     } catch (Exception ex)\r
504     {\r
505       ex.printStackTrace();\r
506       return "Error retrieving alignment in " + format + " format. ";\r
507     }\r
508     return "";\r
509   }\r
510 \r
511   /*\r
512    * (non-Javadoc)\r
513    * \r
514    * @see jalview.bin.JalviewLiteJsApi#getAlignmentOrder()\r
515    */\r
516   public String getAlignmentOrder()\r
517   {\r
518     return getAlignmentOrderFrom(getDefaultTargetFrame());\r
519   }\r
520 \r
521   /*\r
522    * (non-Javadoc)\r
523    * \r
524    * @see\r
525    * jalview.bin.JalviewLiteJsApi#getAlignmentOrderFrom(jalview.appletgui.AlignFrame\r
526    * )\r
527    */\r
528   public String getAlignmentOrderFrom(AlignFrame alf)\r
529   {\r
530     return getAlignmentOrderFrom(alf, separator);\r
531   }\r
532 \r
533   /*\r
534    * (non-Javadoc)\r
535    * \r
536    * @see\r
537    * jalview.bin.JalviewLiteJsApi#getAlignmentOrderFrom(jalview.appletgui.AlignFrame\r
538    * , java.lang.String)\r
539    */\r
540   public String getAlignmentOrderFrom(AlignFrame alf, String sep)\r
541   {\r
542     AlignmentI alorder = alf.getAlignViewport().getAlignment();\r
543     String[] order = new String[alorder.getHeight()];\r
544     for (int i = 0; i < order.length; i++)\r
545     {\r
546       order[i] = alorder.getSequenceAt(i).getName();\r
547     }\r
548     return arrayToSeparatorList(order);\r
549   }\r
550 \r
551   /*\r
552    * (non-Javadoc)\r
553    * \r
554    * @see jalview.bin.JalviewLiteJsApi#orderBy(java.lang.String,\r
555    * java.lang.String)\r
556    */\r
557   public String orderBy(String order, String undoName)\r
558   {\r
559     return orderBy(order, undoName, separator);\r
560   }\r
561 \r
562   /*\r
563    * (non-Javadoc)\r
564    * \r
565    * @see jalview.bin.JalviewLiteJsApi#orderBy(java.lang.String,\r
566    * java.lang.String, java.lang.String)\r
567    */\r
568   public String orderBy(String order, String undoName, String sep)\r
569   {\r
570     return orderAlignmentBy(getDefaultTargetFrame(), order, undoName, sep);\r
571   }\r
572 \r
573   /*\r
574    * (non-Javadoc)\r
575    * \r
576    * @see\r
577    * jalview.bin.JalviewLiteJsApi#orderAlignmentBy(jalview.appletgui.AlignFrame,\r
578    * java.lang.String, java.lang.String, java.lang.String)\r
579    */\r
580   public String orderAlignmentBy(AlignFrame alf, String order,\r
581           String undoName, String sep)\r
582   {\r
583     String[] ids = separatorListToArray(order, sep);\r
584     SequenceI[] sqs = null;\r
585     if (ids != null && ids.length > 0)\r
586     {\r
587       jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(\r
588               alf.viewport.getAlignment().getSequencesArray());\r
589       int s = 0;\r
590       sqs = new SequenceI[ids.length];\r
591       for (int i = 0; i < ids.length; i++)\r
592       {\r
593         if (ids[i].trim().length() == 0)\r
594         {\r
595           continue;\r
596         }\r
597         SequenceI sq = matcher.findIdMatch(ids[i]);\r
598         if (sq != null)\r
599         {\r
600           sqs[s++] = sq;\r
601         }\r
602       }\r
603       if (s > 0)\r
604       {\r
605         SequenceI[] sqq = new SequenceI[s];\r
606         System.arraycopy(sqs, 0, sqq, 0, s);\r
607         sqs = sqq;\r
608       }\r
609       else\r
610       {\r
611         sqs = null;\r
612       }\r
613     }\r
614     if (sqs == null)\r
615     {\r
616       return "";\r
617     }\r
618     ;\r
619     final AlignmentOrder aorder = new AlignmentOrder(sqs);\r
620 \r
621     if (undoName != null && undoName.trim().length() == 0)\r
622     {\r
623       undoName = null;\r
624     }\r
625     final String _undoName = undoName;\r
626     // TODO: deal with synchronization here: cannot raise any events until after\r
627     // this has returned.\r
628     return alf.sortBy(aorder, _undoName) ? "true" : "";\r
629   }\r
630 \r
631   /*\r
632    * (non-Javadoc)\r
633    * \r
634    * @see jalview.bin.JalviewLiteJsApi#getAlignment(java.lang.String)\r
635    */\r
636   public String getAlignment(String format)\r
637   {\r
638     return getAlignmentFrom(getDefaultTargetFrame(), format, "true");\r
639   }\r
640 \r
641   /*\r
642    * (non-Javadoc)\r
643    * \r
644    * @see\r
645    * jalview.bin.JalviewLiteJsApi#getAlignmentFrom(jalview.appletgui.AlignFrame,\r
646    * java.lang.String)\r
647    */\r
648   public String getAlignmentFrom(AlignFrame alf, String format)\r
649   {\r
650     return getAlignmentFrom(alf, format, "true");\r
651   }\r
652 \r
653   /*\r
654    * (non-Javadoc)\r
655    * \r
656    * @see jalview.bin.JalviewLiteJsApi#getAlignment(java.lang.String,\r
657    * java.lang.String)\r
658    */\r
659   public String getAlignment(String format, String suffix)\r
660   {\r
661     return getAlignmentFrom(getDefaultTargetFrame(), format, suffix);\r
662   }\r
663 \r
664   /*\r
665    * (non-Javadoc)\r
666    * \r
667    * @see\r
668    * jalview.bin.JalviewLiteJsApi#getAlignmentFrom(jalview.appletgui.AlignFrame,\r
669    * java.lang.String, java.lang.String)\r
670    */\r
671   public String getAlignmentFrom(AlignFrame alf, String format,\r
672           String suffix)\r
673   {\r
674     try\r
675     {\r
676       boolean seqlimits = suffix.equalsIgnoreCase("true");\r
677 \r
678       String reply = new AppletFormatAdapter().formatSequences(format,\r
679               alf.viewport.getAlignment(), seqlimits);\r
680       return reply;\r
681     } catch (Exception ex)\r
682     {\r
683       ex.printStackTrace();\r
684       return "Error retrieving alignment in " + format + " format. ";\r
685     }\r
686   }\r
687 \r
688   /*\r
689    * (non-Javadoc)\r
690    * \r
691    * @see jalview.bin.JalviewLiteJsApi#loadAnnotation(java.lang.String)\r
692    */\r
693   public void loadAnnotation(String annotation)\r
694   {\r
695     loadAnnotationFrom(getDefaultTargetFrame(), annotation);\r
696   }\r
697 \r
698   /*\r
699    * (non-Javadoc)\r
700    * \r
701    * @see\r
702    * jalview.bin.JalviewLiteJsApi#loadAnnotationFrom(jalview.appletgui.AlignFrame\r
703    * , java.lang.String)\r
704    */\r
705   public void loadAnnotationFrom(AlignFrame alf, String annotation)\r
706   {\r
707     if (new AnnotationFile().readAnnotationFile(alf.getAlignViewport()\r
708             .getAlignment(), annotation, AppletFormatAdapter.PASTE))\r
709     {\r
710       alf.alignPanel.fontChanged();\r
711       alf.alignPanel.setScrollValues(0, 0);\r
712     }\r
713     else\r
714     {\r
715       alf.parseFeaturesFile(annotation, AppletFormatAdapter.PASTE);\r
716     }\r
717   }\r
718 \r
719   /*\r
720    * (non-Javadoc)\r
721    * \r
722    * @see jalview.bin.JalviewLiteJsApi#loadAnnotation(java.lang.String)\r
723    */\r
724   public void loadFeatures(String features, boolean autoenabledisplay)\r
725   {\r
726     loadFeaturesFrom(getDefaultTargetFrame(), features, autoenabledisplay);\r
727   }\r
728 \r
729   /*\r
730    * (non-Javadoc)\r
731    * \r
732    * @see\r
733    * jalview.bin.JalviewLiteJsApi#loadAnnotationFrom(jalview.appletgui.AlignFrame\r
734    * , java.lang.String)\r
735    */\r
736   public boolean loadFeaturesFrom(AlignFrame alf, String features,\r
737           boolean autoenabledisplay)\r
738   {\r
739     return alf.parseFeaturesFile(features, AppletFormatAdapter.PASTE,\r
740             autoenabledisplay);\r
741   }\r
742 \r
743   /*\r
744    * (non-Javadoc)\r
745    * \r
746    * @see jalview.bin.JalviewLiteJsApi#getFeatures(java.lang.String)\r
747    */\r
748   public String getFeatures(String format)\r
749   {\r
750     return getFeaturesFrom(getDefaultTargetFrame(), format);\r
751   }\r
752 \r
753   /*\r
754    * (non-Javadoc)\r
755    * \r
756    * @see\r
757    * jalview.bin.JalviewLiteJsApi#getFeaturesFrom(jalview.appletgui.AlignFrame,\r
758    * java.lang.String)\r
759    */\r
760   public String getFeaturesFrom(AlignFrame alf, String format)\r
761   {\r
762     return alf.outputFeatures(false, format);\r
763   }\r
764 \r
765   /*\r
766    * (non-Javadoc)\r
767    * \r
768    * @see jalview.bin.JalviewLiteJsApi#getAnnotation()\r
769    */\r
770   public String getAnnotation()\r
771   {\r
772     return getAnnotationFrom(getDefaultTargetFrame());\r
773   }\r
774 \r
775   /*\r
776    * (non-Javadoc)\r
777    * \r
778    * @see\r
779    * jalview.bin.JalviewLiteJsApi#getAnnotationFrom(jalview.appletgui.AlignFrame\r
780    * )\r
781    */\r
782   public String getAnnotationFrom(AlignFrame alf)\r
783   {\r
784     return alf.outputAnnotations(false);\r
785   }\r
786 \r
787   /*\r
788    * (non-Javadoc)\r
789    * \r
790    * @see jalview.bin.JalviewLiteJsApi#newView()\r
791    */\r
792   public AlignFrame newView()\r
793   {\r
794     return newViewFrom(getDefaultTargetFrame());\r
795   }\r
796 \r
797   /*\r
798    * (non-Javadoc)\r
799    * \r
800    * @see jalview.bin.JalviewLiteJsApi#newView(java.lang.String)\r
801    */\r
802   public AlignFrame newView(String name)\r
803   {\r
804     return newViewFrom(getDefaultTargetFrame(), name);\r
805   }\r
806 \r
807   /*\r
808    * (non-Javadoc)\r
809    * \r
810    * @see jalview.bin.JalviewLiteJsApi#newViewFrom(jalview.appletgui.AlignFrame)\r
811    */\r
812   public AlignFrame newViewFrom(AlignFrame alf)\r
813   {\r
814     return alf.newView(null);\r
815   }\r
816 \r
817   /*\r
818    * (non-Javadoc)\r
819    * \r
820    * @see jalview.bin.JalviewLiteJsApi#newViewFrom(jalview.appletgui.AlignFrame,\r
821    * java.lang.String)\r
822    */\r
823   public AlignFrame newViewFrom(AlignFrame alf, String name)\r
824   {\r
825     return alf.newView(name);\r
826   }\r
827 \r
828   /*\r
829    * (non-Javadoc)\r
830    * \r
831    * @see jalview.bin.JalviewLiteJsApi#loadAlignment(java.lang.String,\r
832    * java.lang.String)\r
833    */\r
834   public AlignFrame loadAlignment(String text, String title)\r
835   {\r
836     Alignment al = null;\r
837 \r
838     String format = new IdentifyFile().Identify(text,\r
839             AppletFormatAdapter.PASTE);\r
840     try\r
841     {\r
842       al = new AppletFormatAdapter().readFile(text,\r
843               AppletFormatAdapter.PASTE, format);\r
844       if (al.getHeight() > 0)\r
845       {\r
846         return new AlignFrame(al, this, title, false);\r
847       }\r
848     } catch (java.io.IOException ex)\r
849     {\r
850       ex.printStackTrace();\r
851     }\r
852     return null;\r
853   }\r
854 \r
855   /*\r
856    * (non-Javadoc)\r
857    * \r
858    * @see jalview.bin.JalviewLiteJsApi#setMouseoverListener(java.lang.String)\r
859    */\r
860   public void setMouseoverListener(String listener)\r
861   {\r
862     setMouseoverListener(currentAlignFrame, listener);\r
863   }\r
864 \r
865   private Vector<jalview.javascript.JSFunctionExec> javascriptListeners = new Vector<jalview.javascript.JSFunctionExec>();\r
866 \r
867   /*\r
868    * (non-Javadoc)\r
869    * \r
870    * @see\r
871    * jalview.bin.JalviewLiteJsApi#setMouseoverListener(jalview.appletgui.AlignFrame\r
872    * , java.lang.String)\r
873    */\r
874   public void setMouseoverListener(AlignFrame af, String listener)\r
875   {\r
876     if (listener != null)\r
877     {\r
878       listener = listener.trim();\r
879       if (listener.length() == 0)\r
880       {\r
881         System.err\r
882                 .println("jalview Javascript error: Ignoring empty function for mouseover listener.");\r
883         return;\r
884       }\r
885     }\r
886     jalview.javascript.MouseOverListener mol = new jalview.javascript.MouseOverListener(\r
887             this, af, listener);\r
888     javascriptListeners.addElement(mol);\r
889     StructureSelectionManager.getStructureSelectionManager(this)\r
890             .addStructureViewerListener(mol);\r
891     if (debug)\r
892     {\r
893       System.err.println("Added a mouseover listener for "\r
894               + ((af == null) ? "All frames" : "Just views for "\r
895                       + af.getAlignViewport().getSequenceSetId()));\r
896       System.err.println("There are now " + javascriptListeners.size()\r
897               + " listeners in total.");\r
898     }\r
899   }\r
900 \r
901   /*\r
902    * (non-Javadoc)\r
903    * \r
904    * @see jalview.bin.JalviewLiteJsApi#setSelectionListener(java.lang.String)\r
905    */\r
906   public void setSelectionListener(String listener)\r
907   {\r
908     setSelectionListener(null, listener);\r
909   }\r
910 \r
911   /*\r
912    * (non-Javadoc)\r
913    * \r
914    * @see\r
915    * jalview.bin.JalviewLiteJsApi#setSelectionListener(jalview.appletgui.AlignFrame\r
916    * , java.lang.String)\r
917    */\r
918   public void setSelectionListener(AlignFrame af, String listener)\r
919   {\r
920     if (listener != null)\r
921     {\r
922       listener = listener.trim();\r
923       if (listener.length() == 0)\r
924       {\r
925         System.err\r
926                 .println("jalview Javascript error: Ignoring empty function for selection listener.");\r
927         return;\r
928       }\r
929     }\r
930     jalview.javascript.JsSelectionSender mol = new jalview.javascript.JsSelectionSender(\r
931             this, af, listener);\r
932     javascriptListeners.addElement(mol);\r
933     StructureSelectionManager.getStructureSelectionManager(this)\r
934             .addSelectionListener(mol);\r
935     if (debug)\r
936     {\r
937       System.err.println("Added a selection listener for "\r
938               + ((af == null) ? "All frames" : "Just views for "\r
939                       + af.getAlignViewport().getSequenceSetId()));\r
940       System.err.println("There are now " + javascriptListeners.size()\r
941               + " listeners in total.");\r
942     }\r
943   }\r
944 \r
945   /*\r
946    * (non-Javadoc)\r
947    * \r
948    * @see jalview.bin.JalviewLiteJsApi#setStructureListener(java.lang.String,\r
949    * java.lang.String)\r
950    */\r
951   public void setStructureListener(String listener, String modelSet)\r
952   {\r
953     if (listener != null)\r
954     {\r
955       listener = listener.trim();\r
956       if (listener.length() == 0)\r
957       {\r
958         System.err\r
959                 .println("jalview Javascript error: Ignoring empty function for selection listener.");\r
960         return;\r
961       }\r
962     }\r
963     jalview.javascript.MouseOverStructureListener mol = new jalview.javascript.MouseOverStructureListener(\r
964             this, listener, separatorListToArray(modelSet));\r
965     javascriptListeners.addElement(mol);\r
966     StructureSelectionManager.getStructureSelectionManager(this)\r
967             .addStructureViewerListener(mol);\r
968     if (debug)\r
969     {\r
970       System.err.println("Added a javascript structure viewer listener '"\r
971               + listener + "'");\r
972       System.err.println("There are now " + javascriptListeners.size()\r
973               + " listeners in total.");\r
974     }\r
975   }\r
976 \r
977   /*\r
978    * (non-Javadoc)\r
979    * \r
980    * @see\r
981    * jalview.bin.JalviewLiteJsApi#removeJavascriptListener(jalview.appletgui\r
982    * .AlignFrame, java.lang.String)\r
983    */\r
984   public void removeJavascriptListener(AlignFrame af, String listener)\r
985   {\r
986     if (listener != null)\r
987     {\r
988       listener = listener.trim();\r
989       if (listener.length() == 0)\r
990       {\r
991         listener = null;\r
992       }\r
993     }\r
994     boolean rprt = false;\r
995     for (int ms = 0, msSize = javascriptListeners.size(); ms < msSize;)\r
996     {\r
997       Object lstn = javascriptListeners.elementAt(ms);\r
998       JsCallBack lstner = (JsCallBack) lstn;\r
999       if ((af == null || lstner.getAlignFrame() == af)\r
1000               && (listener == null || lstner.getListenerFunction().equals(\r
1001                       listener)))\r
1002       {\r
1003         javascriptListeners.removeElement(lstner);\r
1004         msSize--;\r
1005         if (lstner instanceof SelectionListener)\r
1006         {\r
1007           StructureSelectionManager.getStructureSelectionManager(this)\r
1008                   .removeSelectionListener((SelectionListener) lstner);\r
1009         }\r
1010         else\r
1011         {\r
1012           StructureSelectionManager.getStructureSelectionManager(this)\r
1013                   .removeStructureViewerListener(lstner, null);\r
1014         }\r
1015         rprt = debug;\r
1016         if (debug)\r
1017         {\r
1018           System.err.println("Removed listener '" + listener + "'");\r
1019         }\r
1020       }\r
1021       else\r
1022       {\r
1023         ms++;\r
1024       }\r
1025     }\r
1026     if (rprt)\r
1027     {\r
1028       System.err.println("There are now " + javascriptListeners.size()\r
1029               + " listeners in total.");\r
1030     }\r
1031   }\r
1032 \r
1033   public void stop()\r
1034   {\r
1035     System.err.println("Applet " + getName() + " stop().");\r
1036     tidyUp();\r
1037   }\r
1038 \r
1039   public void destroy()\r
1040   {\r
1041     System.err.println("Applet " + getName() + " destroy().");\r
1042     tidyUp();\r
1043   }\r
1044 \r
1045   private void tidyUp()\r
1046   {\r
1047     removeAll();\r
1048     if (currentAlignFrame != null && currentAlignFrame.viewport != null\r
1049             && currentAlignFrame.viewport.applet != null)\r
1050     {\r
1051       AlignViewport av = currentAlignFrame.viewport;\r
1052       currentAlignFrame.closeMenuItem_actionPerformed();\r
1053       av.applet = null;\r
1054       currentAlignFrame = null;\r
1055     }\r
1056     if (javascriptListeners != null)\r
1057     {\r
1058       while (javascriptListeners.size() > 0)\r
1059       {\r
1060         jalview.javascript.JSFunctionExec mol = javascriptListeners\r
1061                 .elementAt(0);\r
1062         javascriptListeners.removeElement(mol);\r
1063         if (mol instanceof SelectionListener)\r
1064         {\r
1065           StructureSelectionManager.getStructureSelectionManager(this)\r
1066                   .removeSelectionListener((SelectionListener) mol);\r
1067         }\r
1068         else\r
1069         {\r
1070           StructureSelectionManager.getStructureSelectionManager(this)\r
1071                   .removeStructureViewerListener(mol, null);\r
1072         }\r
1073         mol.jvlite = null;\r
1074       }\r
1075     }\r
1076     if (jsFunctionExec != null)\r
1077     {\r
1078       jsFunctionExec.stopQueue();\r
1079       jsFunctionExec.jvlite = null;\r
1080     }\r
1081     initialAlignFrame = null;\r
1082     jsFunctionExec = null;\r
1083     javascriptListeners = null;\r
1084     StructureSelectionManager.release(this);\r
1085   }\r
1086 \r
1087   private jalview.javascript.JSFunctionExec jsFunctionExec;\r
1088 \r
1089   /*\r
1090    * (non-Javadoc)\r
1091    * \r
1092    * @see jalview.bin.JalviewLiteJsApi#mouseOverStructure(java.lang.String,\r
1093    * java.lang.String, java.lang.String)\r
1094    */\r
1095   public void mouseOverStructure(final String pdbResNum,\r
1096           final String chain, final String pdbfile)\r
1097   {\r
1098     final StructureSelectionManagerProvider me = this;\r
1099     java.awt.EventQueue.invokeLater(new Runnable()\r
1100     {\r
1101       @Override\r
1102       public void run()\r
1103       {\r
1104         try\r
1105         {\r
1106           StructureSelectionManager.getStructureSelectionManager(me)\r
1107                   .mouseOverStructure(new Integer(pdbResNum).intValue(),\r
1108                           chain, pdbfile);\r
1109           if (debug)\r
1110           {\r
1111             System.err.println("mouseOver for '" + pdbResNum\r
1112                     + "' in chain '" + chain + "' in structure '" + pdbfile\r
1113                     + "'");\r
1114           }\r
1115         } catch (NumberFormatException e)\r
1116         {\r
1117           System.err.println("Ignoring invalid residue number string '"\r
1118                   + pdbResNum + "'");\r
1119         }\r
1120 \r
1121       }\r
1122     });\r
1123   }\r
1124 \r
1125   /*\r
1126    * (non-Javadoc)\r
1127    * \r
1128    * @see\r
1129    * jalview.bin.JalviewLiteJsApi#scrollViewToIn(jalview.appletgui.AlignFrame,\r
1130    * java.lang.String, java.lang.String)\r
1131    */\r
1132   public void scrollViewToIn(final AlignFrame alf, final String topRow,\r
1133           final String leftHandColumn)\r
1134   {\r
1135     java.awt.EventQueue.invokeLater(new Runnable()\r
1136     {\r
1137       @Override\r
1138       public void run()\r
1139       {\r
1140         try\r
1141         {\r
1142           alf.scrollTo(new Integer(topRow).intValue(), new Integer(\r
1143                   leftHandColumn).intValue());\r
1144 \r
1145         } catch (Exception ex)\r
1146         {\r
1147           System.err.println("Couldn't parse integer arguments (topRow='"\r
1148                   + topRow + "' and leftHandColumn='" + leftHandColumn\r
1149                   + "')");\r
1150           ex.printStackTrace();\r
1151         }\r
1152       }\r
1153     });\r
1154   }\r
1155 \r
1156   /*\r
1157    * (non-Javadoc)\r
1158    * \r
1159    * @see\r
1160    * jalview.javascript.JalviewLiteJsApi#scrollViewToRowIn(jalview.appletgui\r
1161    * .AlignFrame, java.lang.String)\r
1162    */\r
1163   @Override\r
1164   public void scrollViewToRowIn(final AlignFrame alf, final String topRow)\r
1165   {\r
1166 \r
1167     java.awt.EventQueue.invokeLater(new Runnable()\r
1168     {\r
1169       @Override\r
1170       public void run()\r
1171       {\r
1172         try\r
1173         {\r
1174           alf.scrollToRow(new Integer(topRow).intValue());\r
1175 \r
1176         } catch (Exception ex)\r
1177         {\r
1178           System.err.println("Couldn't parse integer arguments (topRow='"\r
1179                   + topRow + "')");\r
1180           ex.printStackTrace();\r
1181         }\r
1182 \r
1183       }\r
1184     });\r
1185   }\r
1186 \r
1187   /*\r
1188    * (non-Javadoc)\r
1189    * \r
1190    * @see\r
1191    * jalview.javascript.JalviewLiteJsApi#scrollViewToColumnIn(jalview.appletgui\r
1192    * .AlignFrame, java.lang.String)\r
1193    */\r
1194   @Override\r
1195   public void scrollViewToColumnIn(final AlignFrame alf,\r
1196           final String leftHandColumn)\r
1197   {\r
1198     java.awt.EventQueue.invokeLater(new Runnable()\r
1199     {\r
1200 \r
1201       @Override\r
1202       public void run()\r
1203       {\r
1204         try\r
1205         {\r
1206           alf.scrollToColumn(new Integer(leftHandColumn).intValue());\r
1207 \r
1208         } catch (Exception ex)\r
1209         {\r
1210           System.err\r
1211                   .println("Couldn't parse integer arguments (leftHandColumn='"\r
1212                           + leftHandColumn + "')");\r
1213           ex.printStackTrace();\r
1214         }\r
1215       }\r
1216     });\r
1217 \r
1218   }\r
1219 \r
1220   // //////////////////////////////////////////////\r
1221   // //////////////////////////////////////////////\r
1222 \r
1223   public static int lastFrameX = 200;\r
1224 \r
1225   public static int lastFrameY = 200;\r
1226 \r
1227   boolean fileFound = true;\r
1228 \r
1229   String file = "No file";\r
1230 \r
1231   Button launcher = new Button("Start Jalview");\r
1232 \r
1233   /**\r
1234    * The currentAlignFrame is static, it will change if and when the user\r
1235    * selects a new window. Note that it will *never* point back to the embedded\r
1236    * AlignFrame if the applet is started as embedded on the page and then\r
1237    * afterwards a new view is created.\r
1238    */\r
1239   public AlignFrame currentAlignFrame = null;\r
1240 \r
1241   /**\r
1242    * This is the first frame to be displayed, and does not change. API calls\r
1243    * will default to this instance if currentAlignFrame is null.\r
1244    */\r
1245   AlignFrame initialAlignFrame = null;\r
1246 \r
1247   boolean embedded = false;\r
1248 \r
1249   private boolean checkForJmol = true;\r
1250 \r
1251   private boolean checkedForJmol = false; // ensure we don't check for jmol\r
1252 \r
1253   // every time the app is re-inited\r
1254 \r
1255   public boolean jmolAvailable = false;\r
1256 \r
1257   private boolean alignPdbStructures = false;\r
1258 \r
1259   /**\r
1260    * use an external structure viewer exclusively (no jmols or MCViews will be\r
1261    * opened by JalviewLite itself)\r
1262    */\r
1263   public boolean useXtrnalSviewer = false;\r
1264 \r
1265   public static boolean debug = false;\r
1266 \r
1267   static String builddate = null, version = null;\r
1268 \r
1269   private static void initBuildDetails()\r
1270   {\r
1271     if (builddate == null)\r
1272     {\r
1273       builddate = "unknown";\r
1274       version = "test";\r
1275       java.net.URL url = JalviewLite.class\r
1276               .getResource("/.build_properties");\r
1277       if (url != null)\r
1278       {\r
1279         try\r
1280         {\r
1281           BufferedReader reader = new BufferedReader(new InputStreamReader(\r
1282                   url.openStream()));\r
1283           String line;\r
1284           while ((line = reader.readLine()) != null)\r
1285           {\r
1286             if (line.indexOf("VERSION") > -1)\r
1287             {\r
1288               version = line.substring(line.indexOf("=") + 1);\r
1289             }\r
1290             if (line.indexOf("BUILD_DATE") > -1)\r
1291             {\r
1292               builddate = line.substring(line.indexOf("=") + 1);\r
1293             }\r
1294           }\r
1295         } catch (Exception ex)\r
1296         {\r
1297           ex.printStackTrace();\r
1298         }\r
1299       }\r
1300     }\r
1301   }\r
1302 \r
1303   public static String getBuildDate()\r
1304   {\r
1305     initBuildDetails();\r
1306     return builddate;\r
1307   }\r
1308 \r
1309   public static String getVersion()\r
1310   {\r
1311     initBuildDetails();\r
1312     return version;\r
1313   }\r
1314 \r
1315   // public JSObject scriptObject = null;\r
1316 \r
1317   /**\r
1318    * init method for Jalview Applet\r
1319    */\r
1320   public void init()\r
1321   {\r
1322     // remove any handlers that might be hanging around from an earlier instance\r
1323     try\r
1324     {\r
1325       if (debug)\r
1326       {\r
1327         System.err.println("Applet context is '"\r
1328                 + getAppletContext().getClass().toString() + "'");\r
1329       }\r
1330       JSObject scriptObject = JSObject.getWindow(this);\r
1331       if (debug && scriptObject != null)\r
1332       {\r
1333         System.err.println("Applet has Javascript callback support.");\r
1334       }\r
1335 \r
1336     } catch (Exception ex)\r
1337     {\r
1338       System.err\r
1339               .println("Warning: No JalviewLite javascript callbacks available.");\r
1340       if (debug)\r
1341       {\r
1342         ex.printStackTrace();\r
1343       }\r
1344     }\r
1345     /**\r
1346      * turn on extra applet debugging\r
1347      */\r
1348     String dbg = getParameter("debug");\r
1349     if (dbg != null)\r
1350     {\r
1351       debug = dbg.toLowerCase().equals("true");\r
1352     }\r
1353     if (debug)\r
1354     {\r
1355 \r
1356       System.err.println("JalviewLite Version " + getVersion());\r
1357       System.err.println("Build Date : " + getBuildDate());\r
1358 \r
1359     }\r
1360     String externalsviewer = getParameter("externalstructureviewer");\r
1361     if (externalsviewer != null)\r
1362     {\r
1363       useXtrnalSviewer = externalsviewer.trim().toLowerCase()\r
1364               .equals("true");\r
1365     }\r
1366     /**\r
1367      * if true disable the check for jmol\r
1368      */\r
1369     String chkforJmol = getParameter("nojmol");\r
1370     if (chkforJmol != null)\r
1371     {\r
1372       checkForJmol = !chkforJmol.equals("true");\r
1373     }\r
1374     /**\r
1375      * get the separator parameter if present\r
1376      */\r
1377     String sep = getParameter("separator");\r
1378     if (sep != null)\r
1379     {\r
1380       if (sep.length() > 0)\r
1381       {\r
1382         separator = sep;\r
1383         if (debug)\r
1384         {\r
1385           System.err.println("Separator set to '" + separator + "'");\r
1386         }\r
1387       }\r
1388       else\r
1389       {\r
1390         throw new Error(\r
1391                 "Invalid separator parameter - must be non-zero length");\r
1392       }\r
1393     }\r
1394     int r = 255;\r
1395     int g = 255;\r
1396     int b = 255;\r
1397     String param = getParameter("RGB");\r
1398 \r
1399     if (param != null)\r
1400     {\r
1401       try\r
1402       {\r
1403         r = Integer.parseInt(param.substring(0, 2), 16);\r
1404         g = Integer.parseInt(param.substring(2, 4), 16);\r
1405         b = Integer.parseInt(param.substring(4, 6), 16);\r
1406       } catch (Exception ex)\r
1407       {\r
1408         r = 255;\r
1409         g = 255;\r
1410         b = 255;\r
1411       }\r
1412     }\r
1413     param = getParameter("label");\r
1414     if (param != null)\r
1415     {\r
1416       launcher.setLabel(param);\r
1417     }\r
1418 \r
1419     setBackground(new Color(r, g, b));\r
1420 \r
1421     file = getParameter("file");\r
1422 \r
1423     if (file == null)\r
1424     {\r
1425       // Maybe the sequences are added as parameters\r
1426       StringBuffer data = new StringBuffer("PASTE");\r
1427       int i = 1;\r
1428       while ((file = getParameter("sequence" + i)) != null)\r
1429       {\r
1430         data.append(file.toString() + "\n");\r
1431         i++;\r
1432       }\r
1433       if (data.length() > 5)\r
1434       {\r
1435         file = data.toString();\r
1436       }\r
1437     }\r
1438 \r
1439     final JalviewLite jvapplet = this;\r
1440     if (getParameter("embedded") != null\r
1441             && getParameter("embedded").equalsIgnoreCase("true"))\r
1442     {\r
1443       // Launch as embedded applet in page\r
1444       embedded = true;\r
1445       LoadingThread loader = new LoadingThread(file, jvapplet);\r
1446       loader.start();\r
1447     }\r
1448     else if (file != null)\r
1449     {\r
1450       if (getParameter("showbutton") == null\r
1451               || !getParameter("showbutton").equalsIgnoreCase("false"))\r
1452       {\r
1453         // Add the JalviewLite 'Button' to the page\r
1454         add(launcher);\r
1455         launcher.addActionListener(new java.awt.event.ActionListener()\r
1456         {\r
1457           public void actionPerformed(ActionEvent e)\r
1458           {\r
1459             LoadingThread loader = new LoadingThread(file, jvapplet);\r
1460             loader.start();\r
1461           }\r
1462         });\r
1463       }\r
1464       else\r
1465       {\r
1466         // Open jalviewLite immediately.\r
1467         LoadingThread loader = new LoadingThread(file, jvapplet);\r
1468         loader.start();\r
1469       }\r
1470     }\r
1471     else\r
1472     {\r
1473       // jalview initialisation with no alignment. loadAlignment() method can\r
1474       // still be called to open new alignments.\r
1475       file = "NO FILE";\r
1476       fileFound = false;\r
1477       // callInitCallback();\r
1478     }\r
1479   }\r
1480 \r
1481   private void callInitCallback()\r
1482   {\r
1483     String initjscallback = getParameter("oninit");\r
1484     if (initjscallback == null)\r
1485     {\r
1486       return;\r
1487     }\r
1488     initjscallback = initjscallback.trim();\r
1489     if (initjscallback.length() > 0)\r
1490     {\r
1491       JSObject scriptObject = null;\r
1492       try\r
1493       {\r
1494         scriptObject = JSObject.getWindow(this);\r
1495       } catch (Exception ex)\r
1496       {\r
1497       }\r
1498       ;\r
1499       if (scriptObject != null)\r
1500       {\r
1501         try\r
1502         {\r
1503           // do onInit with the JS executor thread\r
1504           new JSFunctionExec(this).executeJavascriptFunction(true,\r
1505                   initjscallback, null, "Calling oninit callback '"\r
1506                           + initjscallback + "'.");\r
1507         } catch (Exception e)\r
1508         {\r
1509           System.err.println("Exception when executing _oninit callback '"\r
1510                   + initjscallback + "'.");\r
1511           e.printStackTrace();\r
1512         }\r
1513       }\r
1514       else\r
1515       {\r
1516         System.err.println("Not executing _oninit callback '"\r
1517                 + initjscallback + "' - no scripting allowed.");\r
1518       }\r
1519     }\r
1520   }\r
1521 \r
1522   /**\r
1523    * Initialises and displays a new java.awt.Frame\r
1524    * \r
1525    * @param frame\r
1526    *          java.awt.Frame to be displayed\r
1527    * @param title\r
1528    *          title of new frame\r
1529    * @param width\r
1530    *          width if new frame\r
1531    * @param height\r
1532    *          height of new frame\r
1533    */\r
1534   public static void addFrame(final Frame frame, String title, int width,\r
1535           int height)\r
1536   {\r
1537     frame.setLocation(lastFrameX, lastFrameY);\r
1538     lastFrameX += 40;\r
1539     lastFrameY += 40;\r
1540     frame.setSize(width, height);\r
1541     frame.setTitle(title);\r
1542     frame.addWindowListener(new WindowAdapter()\r
1543     {\r
1544       public void windowClosing(WindowEvent e)\r
1545       {\r
1546         if (frame instanceof AlignFrame)\r
1547         {\r
1548           AlignViewport vp = ((AlignFrame) frame).viewport;\r
1549           ((AlignFrame) frame).closeMenuItem_actionPerformed();\r
1550           if (vp.applet.currentAlignFrame == frame)\r
1551           {\r
1552             vp.applet.currentAlignFrame = null;\r
1553           }\r
1554           vp.applet = null;\r
1555           vp = null;\r
1556 \r
1557         }\r
1558         lastFrameX -= 40;\r
1559         lastFrameY -= 40;\r
1560         if (frame instanceof EmbmenuFrame)\r
1561         {\r
1562           ((EmbmenuFrame) frame).destroyMenus();\r
1563         }\r
1564         frame.setMenuBar(null);\r
1565         frame.dispose();\r
1566       }\r
1567 \r
1568       public void windowActivated(WindowEvent e)\r
1569       {\r
1570         if (frame instanceof AlignFrame)\r
1571         {\r
1572           ((AlignFrame) frame).viewport.applet.currentAlignFrame = (AlignFrame) frame;\r
1573           if (debug)\r
1574           {\r
1575             System.err.println("Activated window " + frame);\r
1576           }\r
1577         }\r
1578         // be good.\r
1579         super.windowActivated(e);\r
1580       }\r
1581       /*\r
1582        * Probably not necessary to do this - see TODO above. (non-Javadoc)\r
1583        * \r
1584        * @see\r
1585        * java.awt.event.WindowAdapter#windowDeactivated(java.awt.event.WindowEvent\r
1586        * )\r
1587        * \r
1588        * public void windowDeactivated(WindowEvent e) { if (currentAlignFrame ==\r
1589        * frame) { currentAlignFrame = null; if (debug) {\r
1590        * System.err.println("Deactivated window "+frame); } }\r
1591        * super.windowDeactivated(e); }\r
1592        */\r
1593     });\r
1594     frame.setVisible(true);\r
1595   }\r
1596 \r
1597   /**\r
1598    * This paints the background surrounding the "Launch Jalview button" <br>\r
1599    * <br>\r
1600    * If file given in parameter not found, displays error message\r
1601    * \r
1602    * @param g\r
1603    *          graphics context\r
1604    */\r
1605   public void paint(Graphics g)\r
1606   {\r
1607     if (!fileFound)\r
1608     {\r
1609       g.setColor(new Color(200, 200, 200));\r
1610       g.setColor(Color.cyan);\r
1611       g.fillRect(0, 0, getSize().width, getSize().height);\r
1612       g.setColor(Color.red);\r
1613       g.drawString("Jalview can't open file", 5, 15);\r
1614       g.drawString("\"" + file + "\"", 5, 30);\r
1615     }\r
1616     else if (embedded)\r
1617     {\r
1618       g.setColor(Color.black);\r
1619       g.setFont(new Font("Arial", Font.BOLD, 24));\r
1620       g.drawString("Jalview Applet", 50, getSize().height / 2 - 30);\r
1621       g.drawString("Loading Data...", 50, getSize().height / 2);\r
1622     }\r
1623   }\r
1624 \r
1625   /**\r
1626    * get all components associated with the applet of the given type\r
1627    * \r
1628    * @param class1\r
1629    * @return\r
1630    */\r
1631   public Vector getAppletWindow(Class class1)\r
1632   {\r
1633     Vector wnds = new Vector();\r
1634     Component[] cmp = getComponents();\r
1635     if (cmp != null)\r
1636     {\r
1637       for (int i = 0; i < cmp.length; i++)\r
1638       {\r
1639         if (class1.isAssignableFrom(cmp[i].getClass()))\r
1640         {\r
1641           wnds.addElement(cmp);\r
1642         }\r
1643       }\r
1644     }\r
1645     return wnds;\r
1646   }\r
1647 \r
1648   class LoadJmolThread extends Thread\r
1649   {\r
1650     private boolean running = false;\r
1651 \r
1652     public void run()\r
1653     {\r
1654       if (running || checkedForJmol)\r
1655       {\r
1656         return;\r
1657       }\r
1658       running = true;\r
1659       if (checkForJmol)\r
1660       {\r
1661         try\r
1662         {\r
1663           if (!System.getProperty("java.version").startsWith("1.1"))\r
1664           {\r
1665             Class.forName("org.jmol.adapter.smarter.SmarterJmolAdapter");\r
1666             jmolAvailable = true;\r
1667           }\r
1668           if (!jmolAvailable)\r
1669           {\r
1670             System.out\r
1671                     .println("Jmol not available - Using MCview for structures");\r
1672           }\r
1673         } catch (java.lang.ClassNotFoundException ex)\r
1674         {\r
1675         }\r
1676       }\r
1677       else\r
1678       {\r
1679         jmolAvailable = false;\r
1680         if (debug)\r
1681         {\r
1682           System.err\r
1683                   .println("Skipping Jmol check. Will use MCView (probably)");\r
1684         }\r
1685       }\r
1686       checkedForJmol = true;\r
1687       running = false;\r
1688     }\r
1689 \r
1690     public boolean notFinished()\r
1691     {\r
1692       return running || !checkedForJmol;\r
1693     }\r
1694   }\r
1695 \r
1696   class LoadingThread extends Thread\r
1697   {\r
1698     /**\r
1699      * State variable: File source\r
1700      */\r
1701     String file;\r
1702 \r
1703     /**\r
1704      * State variable: protocol for access to file source\r
1705      */\r
1706     String protocol;\r
1707 \r
1708     /**\r
1709      * State variable: format of file source\r
1710      */\r
1711     String format;\r
1712 \r
1713     String _file;\r
1714 \r
1715     JalviewLite applet;\r
1716 \r
1717     private void dbgMsg(String msg)\r
1718     {\r
1719       if (applet.debug)\r
1720       {\r
1721         System.err.println(msg);\r
1722       }\r
1723     }\r
1724 \r
1725     /**\r
1726      * update the protocol state variable for accessing the datasource located\r
1727      * by file.\r
1728      * \r
1729      * @param file\r
1730      * @return possibly updated datasource string\r
1731      */\r
1732     public String setProtocolState(String file)\r
1733     {\r
1734       if (file.startsWith("PASTE"))\r
1735       {\r
1736         file = file.substring(5);\r
1737         protocol = AppletFormatAdapter.PASTE;\r
1738       }\r
1739       else if (inArchive(file))\r
1740       {\r
1741         protocol = AppletFormatAdapter.CLASSLOADER;\r
1742       }\r
1743       else\r
1744       {\r
1745         file = addProtocol(file);\r
1746         protocol = AppletFormatAdapter.URL;\r
1747       }\r
1748       dbgMsg("Protocol identified as '" + protocol + "'");\r
1749       return file;\r
1750     }\r
1751 \r
1752     public LoadingThread(String _file, JalviewLite _applet)\r
1753     {\r
1754       this._file = _file;\r
1755       applet = _applet;\r
1756     }\r
1757 \r
1758     public void run()\r
1759     {\r
1760       LoadJmolThread jmolchecker = new LoadJmolThread();\r
1761       jmolchecker.start();\r
1762       while (jmolchecker.notFinished())\r
1763       {\r
1764         // wait around until the Jmol check is complete.\r
1765         try\r
1766         {\r
1767           Thread.sleep(2);\r
1768         } catch (Exception e)\r
1769         {\r
1770         }\r
1771         ;\r
1772       }\r
1773       startLoading();\r
1774       // applet.callInitCallback();\r
1775     }\r
1776 \r
1777     private void startLoading()\r
1778     {\r
1779       AlignFrame newAlignFrame;\r
1780       dbgMsg("Loading thread started with:\n>>file\n" + _file + ">>endfile");\r
1781       file = setProtocolState(_file);\r
1782 \r
1783       format = new jalview.io.IdentifyFile().Identify(file, protocol);\r
1784       dbgMsg("File identified as '" + format + "'");\r
1785       dbgMsg("Loading started.");\r
1786       Alignment al = null;\r
1787       try\r
1788       {\r
1789         al = new AppletFormatAdapter().readFile(file, protocol, format);\r
1790       } catch (java.io.IOException ex)\r
1791       {\r
1792         dbgMsg("File load exception.");\r
1793         ex.printStackTrace();\r
1794         if (debug)\r
1795         {\r
1796           try\r
1797           {\r
1798             FileParse fp = new FileParse(file, protocol);\r
1799             String ln = null;\r
1800             dbgMsg(">>>Dumping contents of '" + file + "' " + "("\r
1801                     + protocol + ")");\r
1802             while ((ln = fp.nextLine()) != null)\r
1803             {\r
1804               dbgMsg(ln);\r
1805             }\r
1806             dbgMsg(">>>Dump finished.");\r
1807           } catch (Exception e)\r
1808           {\r
1809             System.err\r
1810                     .println("Exception when trying to dump the content of the file parameter.");\r
1811             e.printStackTrace();\r
1812           }\r
1813         }\r
1814       }\r
1815       if ((al != null) && (al.getHeight() > 0))\r
1816       {\r
1817         dbgMsg("Successfully loaded file.");\r
1818         newAlignFrame = new AlignFrame(al, applet, file, embedded);\r
1819         if (initialAlignFrame == null)\r
1820         {\r
1821           initialAlignFrame = newAlignFrame;\r
1822         }\r
1823         // update the focus.\r
1824         currentAlignFrame = newAlignFrame;\r
1825 \r
1826         if (protocol == jalview.io.AppletFormatAdapter.PASTE)\r
1827         {\r
1828           newAlignFrame.setTitle("Sequences from "\r
1829                   + applet.getDocumentBase());\r
1830         }\r
1831 \r
1832         newAlignFrame.statusBar.setText("Successfully loaded file " + file);\r
1833 \r
1834         String treeFile = applet.getParameter("tree");\r
1835         if (treeFile == null)\r
1836         {\r
1837           treeFile = applet.getParameter("treeFile");\r
1838         }\r
1839 \r
1840         if (treeFile != null)\r
1841         {\r
1842           try\r
1843           {\r
1844             treeFile = setProtocolState(treeFile);\r
1845             /*\r
1846              * if (inArchive(treeFile)) { protocol =\r
1847              * AppletFormatAdapter.CLASSLOADER; } else { protocol =\r
1848              * AppletFormatAdapter.URL; treeFile = addProtocol(treeFile); }\r
1849              */\r
1850             jalview.io.NewickFile fin = new jalview.io.NewickFile(treeFile,\r
1851                     protocol);\r
1852 \r
1853             fin.parse();\r
1854 \r
1855             if (fin.getTree() != null)\r
1856             {\r
1857               newAlignFrame.loadTree(fin, treeFile);\r
1858               dbgMsg("Successfuly imported tree.");\r
1859             }\r
1860             else\r
1861             {\r
1862               dbgMsg("Tree parameter did not resolve to a valid tree.");\r
1863             }\r
1864           } catch (Exception ex)\r
1865           {\r
1866             ex.printStackTrace();\r
1867           }\r
1868         }\r
1869 \r
1870         /*\r
1871          * Try to load T-Coffee score file\r
1872          */\r
1873         String sScoreFile = applet.getParameter("scoreFile");\r
1874         if (sScoreFile != null && !"".equals(sScoreFile))\r
1875         {\r
1876           try\r
1877           {\r
1878             if (debug)\r
1879             {\r
1880               System.err\r
1881                       .println("Attempting to load T-COFFEE score file from the scoreFile parameter");\r
1882             }\r
1883             if (!newAlignFrame.loadScoreFile(sScoreFile))\r
1884             {\r
1885               System.err\r
1886                       .println("Failed to parse T-COFFEE parameter as a valid score file ('"\r
1887                               + sScoreFile + "')");\r
1888             }\r
1889           } catch (Exception e)\r
1890           {\r
1891             System.err.printf("Cannot read score file: '%s'. Cause: %s \n",\r
1892                     sScoreFile, e.getMessage());\r
1893           }\r
1894         }\r
1895 \r
1896         // ///////////////////////////\r
1897         // modify display of features\r
1898         // we do this before any features have been loaded, ensuring any hidden\r
1899         // groups are hidden when features first displayed\r
1900         //\r
1901         // hide specific groups\r
1902         //\r
1903         String param = applet.getParameter("hidefeaturegroups");\r
1904         if (param != null)\r
1905         {\r
1906           newAlignFrame.setFeatureGroupState(separatorListToArray(param),\r
1907                   false);\r
1908           // applet.setFeatureGroupStateOn(newAlignFrame, param, false);\r
1909         }\r
1910         // show specific groups\r
1911         param = applet.getParameter("showfeaturegroups");\r
1912         if (param != null)\r
1913         {\r
1914           newAlignFrame.setFeatureGroupState(separatorListToArray(param),\r
1915                   true);\r
1916           // applet.setFeatureGroupStateOn(newAlignFrame, param, true);\r
1917         }\r
1918         // and now load features\r
1919         param = applet.getParameter("features");\r
1920         if (param != null)\r
1921         {\r
1922           param = setProtocolState(param);\r
1923 \r
1924           newAlignFrame.parseFeaturesFile(param, protocol);\r
1925         }\r
1926 \r
1927         param = applet.getParameter("showFeatureSettings");\r
1928         if (param != null && param.equalsIgnoreCase("true"))\r
1929         {\r
1930           newAlignFrame.viewport.showSequenceFeatures(true);\r
1931           new FeatureSettings(newAlignFrame.alignPanel);\r
1932         }\r
1933 \r
1934         param = applet.getParameter("annotations");\r
1935         if (param != null)\r
1936         {\r
1937           param = setProtocolState(param);\r
1938 \r
1939           if (new AnnotationFile().readAnnotationFile(\r
1940                   newAlignFrame.viewport.getAlignment(), param, protocol))\r
1941           {\r
1942             newAlignFrame.alignPanel.fontChanged();\r
1943             newAlignFrame.alignPanel.setScrollValues(0, 0);\r
1944           }\r
1945           else\r
1946           {\r
1947             System.err\r
1948                     .println("Annotations were not added from annotation file '"\r
1949                             + param + "'");\r
1950           }\r
1951 \r
1952         }\r
1953 \r
1954         param = applet.getParameter("jnetfile");\r
1955         if (param != null)\r
1956         {\r
1957           try\r
1958           {\r
1959             param = setProtocolState(param);\r
1960             jalview.io.JPredFile predictions = new jalview.io.JPredFile(\r
1961                     param, protocol);\r
1962             JnetAnnotationMaker.add_annotation(predictions,\r
1963                     newAlignFrame.viewport.getAlignment(), 0, false); // false==do\r
1964             // not\r
1965             // add\r
1966             // sequence\r
1967             // profile\r
1968             // from\r
1969             // concise\r
1970             // output\r
1971             newAlignFrame.alignPanel.fontChanged();\r
1972             newAlignFrame.alignPanel.setScrollValues(0, 0);\r
1973           } catch (Exception ex)\r
1974           {\r
1975             ex.printStackTrace();\r
1976           }\r
1977         }\r
1978         /*\r
1979          * <param name="alignpdbfiles" value="false/true"/> Undocumented for 2.6\r
1980          * - related to JAL-434\r
1981          */\r
1982         applet.setAlignPdbStructures(getDefaultParameter("alignpdbfiles",\r
1983                 false));\r
1984         /*\r
1985          * <param name="PDBfile" value="1gaq.txt PDB|1GAQ|1GAQ|A PDB|1GAQ|1GAQ|B\r
1986          * PDB|1GAQ|1GAQ|C">\r
1987          * \r
1988          * <param name="PDBfile2" value="1gaq.txt A=SEQA B=SEQB C=SEQB">\r
1989          * \r
1990          * <param name="PDBfile3" value="1q0o Q45135_9MICO">\r
1991          */\r
1992 \r
1993         int pdbFileCount = 0;\r
1994         // Accumulate pdbs here if they are heading for the same view (if\r
1995         // alignPdbStructures is true)\r
1996         Vector pdbs = new Vector();\r
1997         // create a lazy matcher if we're asked to\r
1998         jalview.analysis.SequenceIdMatcher matcher = (applet\r
1999                 .getDefaultParameter("relaxedidmatch", false)) ? new jalview.analysis.SequenceIdMatcher(\r
2000                 newAlignFrame.getAlignViewport().getAlignment()\r
2001                         .getSequencesArray()) : null;\r
2002 \r
2003         do\r
2004         {\r
2005           if (pdbFileCount > 0)\r
2006           {\r
2007             param = applet.getParameter("PDBFILE" + pdbFileCount);\r
2008           }\r
2009           else\r
2010           {\r
2011             param = applet.getParameter("PDBFILE");\r
2012           }\r
2013 \r
2014           if (param != null)\r
2015           {\r
2016             PDBEntry pdb = new PDBEntry();\r
2017 \r
2018             String seqstring;\r
2019             SequenceI[] seqs = null;\r
2020             String[] chains = null;\r
2021 \r
2022             StringTokenizer st = new StringTokenizer(param, " ");\r
2023 \r
2024             if (st.countTokens() < 2)\r
2025             {\r
2026               String sequence = applet.getParameter("PDBSEQ");\r
2027               if (sequence != null)\r
2028                 seqs = new SequenceI[]\r
2029                 { matcher == null ? (Sequence) newAlignFrame\r
2030                         .getAlignViewport().getAlignment()\r
2031                         .findName(sequence) : matcher.findIdMatch(sequence) };\r
2032 \r
2033             }\r
2034             else\r
2035             {\r
2036               param = st.nextToken();\r
2037               Vector tmp = new Vector();\r
2038               Vector tmp2 = new Vector();\r
2039 \r
2040               while (st.hasMoreTokens())\r
2041               {\r
2042                 seqstring = st.nextToken();\r
2043                 StringTokenizer st2 = new StringTokenizer(seqstring, "=");\r
2044                 if (st2.countTokens() > 1)\r
2045                 {\r
2046                   // This is the chain\r
2047                   tmp2.addElement(st2.nextToken());\r
2048                   seqstring = st2.nextToken();\r
2049                 }\r
2050                 tmp.addElement(matcher == null ? (Sequence) newAlignFrame\r
2051                         .getAlignViewport().getAlignment()\r
2052                         .findName(seqstring) : matcher\r
2053                         .findIdMatch(seqstring));\r
2054               }\r
2055 \r
2056               seqs = new SequenceI[tmp.size()];\r
2057               tmp.copyInto(seqs);\r
2058               if (tmp2.size() == tmp.size())\r
2059               {\r
2060                 chains = new String[tmp2.size()];\r
2061                 tmp2.copyInto(chains);\r
2062               }\r
2063             }\r
2064             param = setProtocolState(param);\r
2065 \r
2066             if (// !jmolAvailable\r
2067             // &&\r
2068             protocol == AppletFormatAdapter.CLASSLOADER\r
2069                     && !useXtrnalSviewer)\r
2070             {\r
2071               // Re: JAL-357 : the bug isn't a problem if we are using an\r
2072               // external viewer!\r
2073               // TODO: verify this Re:\r
2074               // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605\r
2075               // This exception preserves the current behaviour where, even if\r
2076               // the local pdb file was identified in the class loader\r
2077               protocol = AppletFormatAdapter.URL; // this is probably NOT\r
2078               // CORRECT!\r
2079               param = addProtocol(param); //\r
2080             }\r
2081 \r
2082             pdb.setFile(param);\r
2083 \r
2084             if (seqs != null)\r
2085             {\r
2086               for (int i = 0; i < seqs.length; i++)\r
2087               {\r
2088                 if (seqs[i] != null)\r
2089                 {\r
2090                   ((Sequence) seqs[i]).addPDBId(pdb);\r
2091                 }\r
2092                 else\r
2093                 {\r
2094                   if (JalviewLite.debug)\r
2095                   {\r
2096                     // this may not really be a problem but we give a warning\r
2097                     // anyway\r
2098                     System.err\r
2099                             .println("Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence "\r
2100                                     + i + ")");\r
2101                   }\r
2102                 }\r
2103               }\r
2104 \r
2105               if (!alignPdbStructures)\r
2106               {\r
2107                 newAlignFrame.newStructureView(applet, pdb, seqs, chains,\r
2108                         protocol);\r
2109               }\r
2110               else\r
2111               {\r
2112                 pdbs.addElement(new Object[]\r
2113                 { pdb, seqs, chains, new String(protocol) });\r
2114               }\r
2115             }\r
2116           }\r
2117 \r
2118           pdbFileCount++;\r
2119         } while (param != null || pdbFileCount < 10);\r
2120         if (pdbs.size() > 0)\r
2121         {\r
2122           SequenceI[][] seqs = new SequenceI[pdbs.size()][];\r
2123           PDBEntry[] pdb = new PDBEntry[pdbs.size()];\r
2124           String[][] chains = new String[pdbs.size()][];\r
2125           String[] protocols = new String[pdbs.size()];\r
2126           for (int pdbsi = 0, pdbsiSize = pdbs.size(); pdbsi < pdbsiSize; pdbsi++)\r
2127           {\r
2128             Object[] o = (Object[]) pdbs.elementAt(pdbsi);\r
2129             pdb[pdbsi] = (PDBEntry) o[0];\r
2130             seqs[pdbsi] = (SequenceI[]) o[1];\r
2131             chains[pdbsi] = (String[]) o[2];\r
2132             protocols[pdbsi] = (String) o[3];\r
2133           }\r
2134           newAlignFrame.alignedStructureView(applet, pdb, seqs, chains,\r
2135                   protocols);\r
2136 \r
2137         }\r
2138       }\r
2139       else\r
2140       {\r
2141         fileFound = false;\r
2142         applet.remove(launcher);\r
2143         applet.repaint();\r
2144       }\r
2145       callInitCallback();\r
2146     }\r
2147 \r
2148     /**\r
2149      * Discovers whether the given file is in the Applet Archive\r
2150      * \r
2151      * @param file\r
2152      *          String\r
2153      * @return boolean\r
2154      */\r
2155     boolean inArchive(String file)\r
2156     {\r
2157       // This might throw a security exception in certain browsers\r
2158       // Netscape Communicator for instance.\r
2159       try\r
2160       {\r
2161         boolean rtn = (getClass().getResourceAsStream("/" + file) != null);\r
2162         if (debug)\r
2163         {\r
2164           System.err.println("Resource '" + file + "' was "\r
2165                   + (rtn ? "" : "not") + " located by classloader.");\r
2166         }\r
2167         return rtn;\r
2168       } catch (Exception ex)\r
2169       {\r
2170         System.out.println("Exception checking resources: " + file + " "\r
2171                 + ex);\r
2172         return false;\r
2173       }\r
2174     }\r
2175 \r
2176     String addProtocol(String file)\r
2177     {\r
2178       if (file.indexOf("://") == -1)\r
2179       {\r
2180         String fl = applet.resolveUrlForLocalOrAbsolute(file,\r
2181                 getDocumentBase());\r
2182         try\r
2183         {\r
2184           if (new java.net.URL(fl).openStream() != null)\r
2185           {\r
2186             if (debug)\r
2187             {\r
2188               System.err.println("Prepended document base for resource: '"\r
2189                       + file + "'");\r
2190             }\r
2191             return fl;\r
2192           }\r
2193         } catch (Exception x)\r
2194         {\r
2195         }\r
2196         ;\r
2197         fl = applet.resolveUrlForLocalOrAbsolute(file, getCodeBase());\r
2198         try\r
2199         {\r
2200           if (new java.net.URL(fl).openStream() != null)\r
2201           {\r
2202             if (debug)\r
2203             {\r
2204               System.err.println("Prepended codebase for resource: '"\r
2205                       + file + "'");\r
2206             }\r
2207             return fl;\r
2208           }\r
2209         } catch (Exception x)\r
2210         {\r
2211         }\r
2212         ;\r
2213 \r
2214       }\r
2215 \r
2216       return file;\r
2217     }\r
2218   }\r
2219 \r
2220   /**\r
2221    * @return the default alignFrame acted on by the public applet methods. May\r
2222    *         return null with an error message on System.err indicating the\r
2223    *         fact.\r
2224    */\r
2225   public AlignFrame getDefaultTargetFrame()\r
2226   {\r
2227     if (currentAlignFrame != null)\r
2228     {\r
2229       return currentAlignFrame;\r
2230     }\r
2231     if (initialAlignFrame != null)\r
2232     {\r
2233       return initialAlignFrame;\r
2234     }\r
2235     System.err\r
2236             .println("Implementation error: Jalview Applet API cannot work out which AlignFrame to use.");\r
2237     return null;\r
2238   }\r
2239 \r
2240   /**\r
2241    * separator used for separatorList\r
2242    */\r
2243   protected String separator = "" + ((char) 0x00AC); // the default used to be\r
2244                                                      // '|' but many sequence\r
2245                                                      // IDS include pipes.\r
2246 \r
2247   /**\r
2248    * set to enable the URL based javascript execution mechanism\r
2249    */\r
2250   public boolean jsfallbackEnabled = false;\r
2251 \r
2252   /**\r
2253    * parse the string into a list\r
2254    * \r
2255    * @param list\r
2256    * @return elements separated by separator\r
2257    */\r
2258   public String[] separatorListToArray(String list)\r
2259   {\r
2260     return separatorListToArray(list, separator);\r
2261   }\r
2262 \r
2263   /**\r
2264    * parse the string into a list\r
2265    * \r
2266    * @param list\r
2267    * @param separator\r
2268    * @return elements separated by separator\r
2269    */\r
2270   public String[] separatorListToArray(String list, String separator)\r
2271   {\r
2272     // note separator local variable intentionally masks object field\r
2273     int seplen = separator.length();\r
2274     if (list == null || list.equals("") || list.equals(separator))\r
2275       return null;\r
2276     java.util.Vector jv = new Vector();\r
2277     int cp = 0, pos;\r
2278     while ((pos = list.indexOf(separator, cp)) > cp)\r
2279     {\r
2280       jv.addElement(list.substring(cp, pos));\r
2281       cp = pos + seplen;\r
2282     }\r
2283     if (cp < list.length())\r
2284     {\r
2285       String c = list.substring(cp);\r
2286       if (!c.equals(separator))\r
2287       {\r
2288         jv.addElement(c);\r
2289       }\r
2290     }\r
2291     if (jv.size() > 0)\r
2292     {\r
2293       String[] v = new String[jv.size()];\r
2294       for (int i = 0; i < v.length; i++)\r
2295       {\r
2296         v[i] = (String) jv.elementAt(i);\r
2297       }\r
2298       jv.removeAllElements();\r
2299       if (debug)\r
2300       {\r
2301         System.err.println("Array from '" + separator\r
2302                 + "' separated List:\n" + v.length);\r
2303         for (int i = 0; i < v.length; i++)\r
2304         {\r
2305           System.err.println("item " + i + " '" + v[i] + "'");\r
2306         }\r
2307       }\r
2308       return v;\r
2309     }\r
2310     if (debug)\r
2311     {\r
2312       System.err.println("Empty Array from '" + separator\r
2313               + "' separated List");\r
2314     }\r
2315     return null;\r
2316   }\r
2317 \r
2318   /**\r
2319    * concatenate the list with separator\r
2320    * \r
2321    * @param list\r
2322    * @return concatenated string\r
2323    */\r
2324   public String arrayToSeparatorList(String[] list)\r
2325   {\r
2326     return arrayToSeparatorList(list, separator);\r
2327   }\r
2328 \r
2329   /**\r
2330    * concatenate the list with separator\r
2331    * \r
2332    * @param list\r
2333    * @param separator\r
2334    * @return concatenated string\r
2335    */\r
2336   public String arrayToSeparatorList(String[] list, String separator)\r
2337   {\r
2338     StringBuffer v = new StringBuffer();\r
2339     if (list != null && list.length > 0)\r
2340     {\r
2341       for (int i = 0, iSize = list.length; i < iSize; i++)\r
2342       {\r
2343         if (list[i] != null)\r
2344         {\r
2345           if (i > 0)\r
2346           {\r
2347             v.append(separator);\r
2348           }\r
2349           v.append(list[i]);\r
2350         }\r
2351       }\r
2352       if (debug)\r
2353       {\r
2354         System.err.println("Returning '" + separator\r
2355                 + "' separated List:\n");\r
2356         System.err.println(v);\r
2357       }\r
2358       return v.toString();\r
2359     }\r
2360     if (debug)\r
2361     {\r
2362       System.err.println("Returning empty '" + separator\r
2363               + "' separated List\n");\r
2364     }\r
2365     return "" + separator;\r
2366   }\r
2367 \r
2368   /*\r
2369    * (non-Javadoc)\r
2370    * \r
2371    * @see jalview.bin.JalviewLiteJsApi#getFeatureGroups()\r
2372    */\r
2373   public String getFeatureGroups()\r
2374   {\r
2375     String lst = arrayToSeparatorList(getDefaultTargetFrame()\r
2376             .getFeatureGroups());\r
2377     return lst;\r
2378   }\r
2379 \r
2380   /*\r
2381    * (non-Javadoc)\r
2382    * \r
2383    * @see\r
2384    * jalview.bin.JalviewLiteJsApi#getFeatureGroupsOn(jalview.appletgui.AlignFrame\r
2385    * )\r
2386    */\r
2387   public String getFeatureGroupsOn(AlignFrame alf)\r
2388   {\r
2389     String lst = arrayToSeparatorList(alf.getFeatureGroups());\r
2390     return lst;\r
2391   }\r
2392 \r
2393   /*\r
2394    * (non-Javadoc)\r
2395    * \r
2396    * @see jalview.bin.JalviewLiteJsApi#getFeatureGroupsOfState(boolean)\r
2397    */\r
2398   public String getFeatureGroupsOfState(boolean visible)\r
2399   {\r
2400     return arrayToSeparatorList(getDefaultTargetFrame()\r
2401             .getFeatureGroupsOfState(visible));\r
2402   }\r
2403 \r
2404   /*\r
2405    * (non-Javadoc)\r
2406    * \r
2407    * @see\r
2408    * jalview.bin.JalviewLiteJsApi#getFeatureGroupsOfStateOn(jalview.appletgui\r
2409    * .AlignFrame, boolean)\r
2410    */\r
2411   public String getFeatureGroupsOfStateOn(AlignFrame alf, boolean visible)\r
2412   {\r
2413     return arrayToSeparatorList(alf.getFeatureGroupsOfState(visible));\r
2414   }\r
2415 \r
2416   /*\r
2417    * (non-Javadoc)\r
2418    * \r
2419    * @see jalview.bin.JalviewLiteJsApi#setFeatureGroupStateOn(jalview.appletgui.\r
2420    * AlignFrame, java.lang.String, boolean)\r
2421    */\r
2422   public void setFeatureGroupStateOn(final AlignFrame alf,\r
2423           final String groups, boolean state)\r
2424   {\r
2425     final boolean st = state;// !(state==null || state.equals("") ||\r
2426     // state.toLowerCase().equals("false"));\r
2427     java.awt.EventQueue.invokeLater(new Runnable()\r
2428     {\r
2429       @Override\r
2430       public void run()\r
2431       {\r
2432         alf.setFeatureGroupState(separatorListToArray(groups), st);\r
2433       }\r
2434     });\r
2435   }\r
2436 \r
2437   /*\r
2438    * (non-Javadoc)\r
2439    * \r
2440    * @see jalview.bin.JalviewLiteJsApi#setFeatureGroupState(java.lang.String,\r
2441    * boolean)\r
2442    */\r
2443   public void setFeatureGroupState(String groups, boolean state)\r
2444   {\r
2445     setFeatureGroupStateOn(getDefaultTargetFrame(), groups, state);\r
2446   }\r
2447 \r
2448   /*\r
2449    * (non-Javadoc)\r
2450    * \r
2451    * @see jalview.bin.JalviewLiteJsApi#getSeparator()\r
2452    */\r
2453   public String getSeparator()\r
2454   {\r
2455     return separator;\r
2456   }\r
2457 \r
2458   /*\r
2459    * (non-Javadoc)\r
2460    * \r
2461    * @see jalview.bin.JalviewLiteJsApi#setSeparator(java.lang.String)\r
2462    */\r
2463   public void setSeparator(String separator)\r
2464   {\r
2465     if (separator == null || separator.length() < 1)\r
2466     {\r
2467       // reset to default\r
2468       separator = "" + ((char) 0x00AC);\r
2469     }\r
2470     this.separator = separator;\r
2471     if (debug)\r
2472     {\r
2473       System.err.println("Default Separator now: '" + separator + "'");\r
2474     }\r
2475   }\r
2476 \r
2477   /**\r
2478    * get boolean value of applet parameter 'name' and return default if\r
2479    * parameter is not set\r
2480    * \r
2481    * @param name\r
2482    *          name of paremeter\r
2483    * @param def\r
2484    *          the value to return otherwise\r
2485    * @return true or false\r
2486    */\r
2487   public boolean getDefaultParameter(String name, boolean def)\r
2488   {\r
2489     String stn;\r
2490     if ((stn = getParameter(name)) == null)\r
2491     {\r
2492       return def;\r
2493     }\r
2494     if (stn.toLowerCase().equals("true"))\r
2495     {\r
2496       return true;\r
2497     }\r
2498     return false;\r
2499   }\r
2500 \r
2501   /*\r
2502    * (non-Javadoc)\r
2503    * \r
2504    * @see jalview.bin.JalviewLiteJsApi#addPdbFile(jalview.appletgui.AlignFrame,\r
2505    * java.lang.String, java.lang.String, java.lang.String)\r
2506    */\r
2507   public boolean addPdbFile(AlignFrame alFrame, String sequenceId,\r
2508           String pdbEntryString, String pdbFile)\r
2509   {\r
2510     return alFrame.addPdbFile(sequenceId, pdbEntryString, pdbFile);\r
2511   }\r
2512 \r
2513   protected void setAlignPdbStructures(boolean alignPdbStructures)\r
2514   {\r
2515     this.alignPdbStructures = alignPdbStructures;\r
2516   }\r
2517 \r
2518   public boolean isAlignPdbStructures()\r
2519   {\r
2520     return alignPdbStructures;\r
2521   }\r
2522 \r
2523   public void start()\r
2524   {\r
2525     // callInitCallback();\r
2526   }\r
2527 \r
2528   private Hashtable<String, long[]> jshashes = new Hashtable<String, long[]>();\r
2529 \r
2530   private Hashtable<String, Hashtable<String, String[]>> jsmessages = new Hashtable<String, Hashtable<String, String[]>>();\r
2531 \r
2532   public void setJsMessageSet(String messageclass, String viewId,\r
2533           String[] colcommands)\r
2534   {\r
2535     Hashtable<String, String[]> msgset = jsmessages.get(messageclass);\r
2536     if (msgset == null)\r
2537     {\r
2538       msgset = new Hashtable<String, String[]>();\r
2539       jsmessages.put(messageclass, msgset);\r
2540     }\r
2541     msgset.put(viewId, colcommands);\r
2542     long[] l = new long[colcommands.length];\r
2543     for (int i = 0; i < colcommands.length; i++)\r
2544     {\r
2545       l[i] = colcommands[i].hashCode();\r
2546     }\r
2547     jshashes.put(messageclass + "|" + viewId, l);\r
2548   }\r
2549 \r
2550   /*\r
2551    * (non-Javadoc)\r
2552    * \r
2553    * @see jalview.bin.JalviewLiteJsApi#getJsMessage(java.lang.String,\r
2554    * java.lang.String)\r
2555    */\r
2556   public String getJsMessage(String messageclass, String viewId)\r
2557   {\r
2558     Hashtable<String, String[]> msgset = jsmessages.get(messageclass);\r
2559     if (msgset != null)\r
2560     {\r
2561       String[] msgs = msgset.get(viewId);\r
2562       if (msgs != null)\r
2563       {\r
2564         for (int i = 0; i < msgs.length; i++)\r
2565         {\r
2566           if (msgs[i] != null)\r
2567           {\r
2568             String m = msgs[i];\r
2569             msgs[i] = null;\r
2570             return m;\r
2571           }\r
2572         }\r
2573       }\r
2574     }\r
2575     return "";\r
2576   }\r
2577 \r
2578   public boolean isJsMessageSetChanged(String string, String string2,\r
2579           String[] colcommands)\r
2580   {\r
2581     long[] l = jshashes.get(string + "|" + string2);\r
2582     if (l == null && colcommands != null)\r
2583     {\r
2584       return true;\r
2585     }\r
2586     for (int i = 0; i < colcommands.length; i++)\r
2587     {\r
2588       if (l[i] != colcommands[i].hashCode())\r
2589       {\r
2590         return true;\r
2591       }\r
2592     }\r
2593     return false;\r
2594   }\r
2595 \r
2596   private Vector jsExecQueue = new Vector();\r
2597 \r
2598   public Vector getJsExecQueue()\r
2599   {\r
2600     return jsExecQueue;\r
2601   }\r
2602 \r
2603   public void setExecutor(JSFunctionExec jsFunctionExec2)\r
2604   {\r
2605     jsFunctionExec = jsFunctionExec2;\r
2606   }\r
2607 \r
2608   /**\r
2609    * return the given colour value parameter or the given default if parameter\r
2610    * not given\r
2611    * \r
2612    * @param colparam\r
2613    * @param defcolour\r
2614    * @return\r
2615    */\r
2616   public Color getDefaultColourParameter(String colparam, Color defcolour)\r
2617   {\r
2618     String colprop = getParameter(colparam);\r
2619     if (colprop == null || colprop.trim().length() == 0)\r
2620     {\r
2621       return defcolour;\r
2622     }\r
2623     Color col = jalview.schemes.ColourSchemeProperty\r
2624             .getAWTColorFromName(colprop);\r
2625     if (col == null)\r
2626     {\r
2627       try\r
2628       {\r
2629         col = new jalview.schemes.UserColourScheme(colprop).findColour('A');\r
2630       } catch (Exception ex)\r
2631       {\r
2632         System.err.println("Couldn't parse '" + colprop\r
2633                 + "' as a colour for " + colparam);\r
2634         col = null;\r
2635       }\r
2636     }\r
2637     return (col == null) ? defcolour : col;\r
2638 \r
2639   }\r
2640 \r
2641   public void openJalviewHelpUrl()\r
2642   {\r
2643     String helpUrl = getParameter("jalviewhelpurl");\r
2644     if (helpUrl == null || helpUrl.trim().length() < 5)\r
2645     {\r
2646       helpUrl = "http://www.jalview.org/help.html";\r
2647     }\r
2648     showURL(helpUrl, "HELP");\r
2649   }\r
2650 \r
2651   /**\r
2652    * form a complete URL given a path to a resource and a reference location on\r
2653    * the same server\r
2654    * \r
2655    * @param url\r
2656    *          - an absolute path on the same server as localref or a document\r
2657    *          located relative to localref\r
2658    * @param localref\r
2659    *          - a URL on the same server as url\r
2660    * @return a complete URL for the resource located by url\r
2661    */\r
2662   private String resolveUrlForLocalOrAbsolute(String url, URL localref)\r
2663   {\r
2664     String codebase = localref.toString();\r
2665     if (url.indexOf("/") == 0)\r
2666     {\r
2667       url = codebase.substring(0, codebase.length()\r
2668               - localref.getFile().length())\r
2669               + url;\r
2670     }\r
2671     else\r
2672     {\r
2673       url = localref + url;\r
2674     }\r
2675     return url;\r
2676   }\r
2677 \r
2678   /**\r
2679    * open a URL in the browser - resolving it according to relative refs and\r
2680    * coping with javascript: protocol if necessary.\r
2681    * \r
2682    * @param url\r
2683    * @param target\r
2684    */\r
2685   public void showURL(String url, String target)\r
2686   {\r
2687     try\r
2688     {\r
2689       if (url.indexOf(":") == -1)\r
2690       {\r
2691         // TODO: verify (Bas Vroling bug) prepend codebase or server URL to\r
2692         // form valid URL\r
2693         // Should really use docbase, not codebase.\r
2694         URL prepend;\r
2695         url = resolveUrlForLocalOrAbsolute(\r
2696                 url,\r
2697                 prepend = getDefaultParameter("resolvetocodebase", false) ? getDocumentBase()\r
2698                         : getCodeBase());\r
2699         if (debug)\r
2700         {\r
2701           System.err\r
2702                   .println("Show url (prepended "\r
2703                           + prepend\r
2704                           + " - toggle resolvetocodebase if code/docbase resolution is wrong): "\r
2705                           + url);\r
2706         }\r
2707       }\r
2708       else\r
2709       {\r
2710         if (debug)\r
2711         {\r
2712           System.err.println("Show url: " + url);\r
2713         }\r
2714       }\r
2715       if (url.indexOf("javascript:") == 0)\r
2716       {\r
2717         // no target for the javascript context\r
2718         getAppletContext().showDocument(new java.net.URL(url));\r
2719       }\r
2720       else\r
2721       {\r
2722         getAppletContext().showDocument(new java.net.URL(url), target);\r
2723       }\r
2724     } catch (Exception ex)\r
2725     {\r
2726       ex.printStackTrace();\r
2727     }\r
2728   }\r
2729 \r
2730   /**\r
2731    * bind structures in a viewer to any matching sequences in an alignFrame (use\r
2732    * sequenceIds to limit scope of search to specific sequences)\r
2733    * \r
2734    * @param alFrame\r
2735    * @param viewer\r
2736    * @param sequenceIds\r
2737    * @return TODO: consider making an exception structure for indicating when\r
2738    *         binding fails public SequenceStructureBinding\r
2739    *         addStructureViewInstance( AlignFrame alFrame, Object viewer, String\r
2740    *         sequenceIds) {\r
2741    * \r
2742    *         if (sequenceIds != null && sequenceIds.length() > 0) { return\r
2743    *         alFrame.addStructureViewInstance(viewer,\r
2744    *         separatorListToArray(sequenceIds)); } else { return\r
2745    *         alFrame.addStructureViewInstance(viewer, null); } // return null; }\r
2746    */\r
2747 }\r