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