0f275dee19c4984385b8be614b2566e1d7caeee6
[jalview.git] / src / jalview / appletgui / AlignFrame.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 \r
20 package jalview.appletgui;\r
21 \r
22 import jalview.jbappletgui.GAlignFrame;\r
23 import jalview.schemes.*;\r
24 import jalview.datamodel.*;\r
25 import jalview.analysis.*;\r
26 import jalview.io.*;\r
27 import java.awt.*;\r
28 import java.awt.event.*;\r
29 import java.util.*;\r
30 import java.io.InputStreamReader;\r
31 import java.io.BufferedReader;\r
32 \r
33 public class AlignFrame\r
34     extends GAlignFrame\r
35 {\r
36   final AlignmentPanel alignPanel;\r
37   final AlignViewport viewport;\r
38   int NEW_WINDOW_WIDTH = 700;\r
39   int NEW_WINDOW_HEIGHT = 500;\r
40   jalview.bin.JalviewLite applet;\r
41 \r
42 \r
43   public AlignFrame(AlignmentI al, jalview.bin.JalviewLite applet, String title)\r
44   {\r
45     this.applet = applet;\r
46     viewport = new AlignViewport(al, applet);\r
47     alignPanel = new AlignmentPanel(this, viewport);\r
48     add(alignPanel);\r
49     alignPanel.validate();\r
50 \r
51     if(applet!=null)\r
52     {\r
53       String treeFile = applet.getParameter("treeFile");\r
54       if (treeFile != null)\r
55       {\r
56         try\r
57         {\r
58           treeFile = treeFile;\r
59           jalview.io.NewickFile fin = new jalview.io.NewickFile(applet.\r
60               getCodeBase() + treeFile, "URL");\r
61           fin.parse();\r
62 \r
63           if (fin.getTree() != null)\r
64           {\r
65             TreePanel tp = null;\r
66             tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),\r
67                                fin, "FromFile", applet.getCodeBase() + treeFile);\r
68             jalview.bin.JalviewLite.addFrame(tp, treeFile, 600, 500);\r
69             addTreeMenuItem(tp, treeFile);\r
70           }\r
71         }\r
72         catch (Exception ex)\r
73         {\r
74           ex.printStackTrace();\r
75         }\r
76       }\r
77 \r
78       String param = applet.getParameter("sortBy");\r
79       if (param != null)\r
80       {\r
81         if (param.equalsIgnoreCase("Id"))\r
82           sortIDMenuItem_actionPerformed(null);\r
83         else if (param.equalsIgnoreCase("Pairwise Identity"))\r
84           sortPairwiseMenuItem_actionPerformed(null);\r
85       }\r
86 \r
87       param = applet.getParameter("wrap");\r
88       if (param != null)\r
89       {\r
90         if (param.equalsIgnoreCase("true"))\r
91         {\r
92           wrapMenuItem.setState(true);\r
93           wrapMenuItem_actionPerformed(null);\r
94         }\r
95       }\r
96 \r
97       try\r
98       {\r
99         param = applet.getParameter("windowWidth");\r
100         if (param != null)\r
101         {\r
102           int width = Integer.parseInt(param);\r
103           NEW_WINDOW_WIDTH = width;\r
104         }\r
105         param = applet.getParameter("windowHeight");\r
106         if (param != null)\r
107         {\r
108           int height = Integer.parseInt(param);\r
109           NEW_WINDOW_HEIGHT = height;\r
110         }\r
111       }\r
112       catch (Exception ex)\r
113       {}\r
114 \r
115     }\r
116 \r
117     this.addWindowListener(new WindowAdapter()\r
118     {\r
119       public void windowClosing(WindowEvent e)\r
120           {\r
121             closeMenuItem_actionPerformed(null);\r
122           }\r
123     });\r
124 \r
125     viewport.addPropertyChangeListener(new java.beans.PropertyChangeListener()\r
126     {\r
127      public void propertyChange(java.beans.PropertyChangeEvent evt)\r
128      {\r
129        if (evt.getPropertyName().equals("alignment"))\r
130        {\r
131          alignmentChanged();\r
132        }\r
133      }\r
134    });\r
135 \r
136    jalview.bin.JalviewLite.addFrame(this, title,\r
137                                     NEW_WINDOW_WIDTH,\r
138                                     NEW_WINDOW_HEIGHT);\r
139 \r
140 \r
141   }\r
142 \r
143   public void inputText_actionPerformed(ActionEvent e)\r
144   {\r
145     CutAndPasteTransfer cap = new CutAndPasteTransfer(true, applet);\r
146     Frame frame = new Frame();\r
147     frame.add(cap);\r
148     jalview.bin.JalviewLite.addFrame(frame, "Cut & Paste Input", 500, 500);\r
149   }\r
150 \r
151   protected void outputText_actionPerformed(ActionEvent e)\r
152   {\r
153     CutAndPasteTransfer cap = new CutAndPasteTransfer(false, applet);\r
154     Frame frame = new Frame();\r
155     frame.add(cap);\r
156     jalview.bin.JalviewLite.addFrame(frame,\r
157                                      "Alignment output - " + e.getActionCommand(),\r
158                                      600, 500);\r
159     cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),\r
160                                               viewport.getAlignment().\r
161                                               getSequences()));\r
162   }\r
163 \r
164   public void closeMenuItem_actionPerformed(ActionEvent e)\r
165   {\r
166     PaintRefresher.components.remove(viewport.alignment);\r
167     dispose();\r
168     if(PaintRefresher.components.size()==0 && applet==null)\r
169       System.exit(0);\r
170   }\r
171 \r
172   Stack historyList = new Stack();\r
173   Stack redoList = new Stack();\r
174 \r
175   void updateEditMenuBar()\r
176   {\r
177     if (historyList.size() > 0)\r
178     {\r
179       undoMenuItem.setEnabled(true);\r
180       HistoryItem hi = (HistoryItem) historyList.peek();\r
181       undoMenuItem.setLabel("Undo " + hi.getDescription());\r
182     }\r
183     else\r
184     {\r
185       undoMenuItem.setEnabled(false);\r
186       undoMenuItem.setLabel("Undo");\r
187     }\r
188 \r
189     if (redoList.size() > 0)\r
190     {\r
191       redoMenuItem.setEnabled(true);\r
192       HistoryItem hi = (HistoryItem) redoList.peek();\r
193       redoMenuItem.setLabel("Redo " + hi.getDescription());\r
194     }\r
195     else\r
196     {\r
197       redoMenuItem.setEnabled(false);\r
198       redoMenuItem.setLabel("Redo");\r
199     }\r
200   }\r
201 \r
202   public void addHistoryItem(HistoryItem hi)\r
203   {\r
204     historyList.push(hi);\r
205     updateEditMenuBar();\r
206   }\r
207 \r
208   protected void undoMenuItem_actionPerformed(ActionEvent e)\r
209   {\r
210     HistoryItem hi = (HistoryItem) historyList.pop();\r
211     redoList.push(new HistoryItem(hi.getDescription(), viewport.alignment,\r
212                                   HistoryItem.HIDE));\r
213     restoreHistoryItem(hi);\r
214     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
215   }\r
216 \r
217   protected void redoMenuItem_actionPerformed(ActionEvent e)\r
218   {\r
219     HistoryItem hi = (HistoryItem) redoList.pop();\r
220     restoreHistoryItem(hi);\r
221     updateEditMenuBar();\r
222     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
223   }\r
224 \r
225   // used by undo and redo\r
226   void restoreHistoryItem(HistoryItem hi)\r
227   {\r
228     if (hi.getType() == HistoryItem.SORT)\r
229     {\r
230       for (int i = 0; i < hi.getSequences().size(); i++)\r
231       {\r
232         viewport.alignment.getSequences().setElementAt(hi.getSequences().\r
233             elementAt(i), i);\r
234       }\r
235     }\r
236     else\r
237     {\r
238       for (int i = 0; i < hi.getSequences().size(); i++)\r
239       {\r
240         SequenceI restore = (SequenceI) hi.getSequences().elementAt(i);\r
241         if (restore.getLength() == 0)\r
242         {\r
243           // log.System.out.println(hi.getHidden().elementAt(i));\r
244           restore.setSequence(hi.getHidden().elementAt(i).toString());\r
245           viewport.alignment.getSequences().insertElementAt(\r
246               restore,\r
247               hi.getAlignIndex(i));\r
248         }\r
249         else\r
250         {\r
251           restore.setSequence(hi.getHidden().elementAt(i).toString());\r
252         }\r
253       }\r
254       if (hi.getType() == HistoryItem.PASTE)\r
255       {\r
256         for (int i = viewport.alignment.getHeight() - 1;\r
257              i > hi.getSequences().size() - 1; i--)\r
258         {\r
259           viewport.alignment.deleteSequence(i);\r
260         }\r
261       }\r
262     }\r
263 \r
264     updateEditMenuBar();\r
265 \r
266     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
267   }\r
268 \r
269   public void moveSelectedSequences(boolean up)\r
270   {\r
271     SequenceGroup sg = viewport.getSelectionGroup();\r
272     if (sg == null)\r
273     {\r
274       return;\r
275     }\r
276 \r
277     if (up)\r
278     {\r
279       for (int i = 1; i < viewport.alignment.getHeight(); i++)\r
280       {\r
281         SequenceI seq = viewport.alignment.getSequenceAt(i);\r
282         if (!sg.sequences.contains(seq))\r
283         {\r
284           continue;\r
285         }\r
286 \r
287         SequenceI temp = viewport.alignment.getSequenceAt(i - 1);\r
288         if (sg.sequences.contains(temp))\r
289         {\r
290           continue;\r
291         }\r
292 \r
293         viewport.alignment.getSequences().setElementAt(temp, i);\r
294         viewport.alignment.getSequences().setElementAt(seq, i - 1);\r
295       }\r
296     }\r
297     else\r
298     {\r
299       for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)\r
300       {\r
301         SequenceI seq = viewport.alignment.getSequenceAt(i);\r
302         if (!sg.sequences.contains(seq))\r
303         {\r
304           continue;\r
305         }\r
306 \r
307         SequenceI temp = viewport.alignment.getSequenceAt(i + 1);\r
308         if (sg.sequences.contains(temp))\r
309         {\r
310           continue;\r
311         }\r
312 \r
313         viewport.alignment.getSequences().setElementAt(temp, i);\r
314         viewport.alignment.getSequences().setElementAt(seq, i + 1);\r
315       }\r
316     }\r
317 \r
318     alignPanel.repaint();\r
319   }\r
320 \r
321   StringBuffer copiedSequences;\r
322   protected void copy_actionPerformed(ActionEvent e)\r
323   {\r
324     if (viewport.getSelectionGroup() == null)\r
325     {\r
326       return;\r
327     }\r
328 \r
329     SequenceGroup sg = viewport.getSelectionGroup();\r
330     copiedSequences = new StringBuffer();\r
331     Hashtable orderedSeqs = new Hashtable();\r
332     for (int i = 0; i < sg.getSize(); i++)\r
333     {\r
334       SequenceI seq = sg.getSequenceAt(i);\r
335       int index = viewport.alignment.findIndex(seq);\r
336       orderedSeqs.put(index + "", seq);\r
337     }\r
338 \r
339     int index = 0, startRes, endRes;\r
340     char ch;\r
341 \r
342     for (int i = 0; i < sg.getSize(); i++)\r
343     {\r
344         SequenceI seq = null;\r
345 \r
346         while (seq == null)\r
347         {\r
348             if (orderedSeqs.containsKey(index + ""))\r
349             {\r
350                 seq = (SequenceI) orderedSeqs.get(index + "");\r
351                 index++;\r
352 \r
353                 break;\r
354             }\r
355             else\r
356             {\r
357                 index++;\r
358             }\r
359         }\r
360 \r
361         //FIND START RES\r
362         //Returns residue following index if gap\r
363         startRes = seq.findPosition(sg.getStartRes());\r
364 \r
365         //FIND END RES\r
366         //Need to find the residue preceeding index if gap\r
367         endRes = 0;\r
368 \r
369         for (int j = 0; j < sg.getEndRes()+1 && j < seq.getLength(); j++)\r
370         {\r
371           ch = seq.getCharAt(j);\r
372           if (!jalview.util.Comparison.isGap( (ch)))\r
373           {\r
374             endRes++;\r
375           }\r
376         }\r
377 \r
378         if(endRes>0)\r
379         {\r
380           endRes += seq.getStart() -1;\r
381         }\r
382 \r
383         copiedSequences.append(seq.getName() + "\t" +\r
384             startRes + "\t" +\r
385             endRes + "\t" +\r
386             seq.getSequence(sg.getStartRes(),\r
387                 sg.getEndRes() + 1) + "\n");\r
388     }\r
389 \r
390   }\r
391 \r
392   protected void pasteNew_actionPerformed(ActionEvent e)\r
393   {\r
394     paste(true);\r
395   }\r
396 \r
397   protected void pasteThis_actionPerformed(ActionEvent e)\r
398   {\r
399     addHistoryItem(new HistoryItem("Paste Sequences", viewport.alignment,\r
400                                    HistoryItem.PASTE));\r
401     paste(false);\r
402   }\r
403 \r
404   void paste(boolean newAlignment)\r
405   {\r
406     try\r
407     {\r
408       if (copiedSequences == null)\r
409       {\r
410         return;\r
411       }\r
412 \r
413       StringTokenizer st = new StringTokenizer(copiedSequences.toString());\r
414       Vector seqs = new Vector();\r
415       while (st.hasMoreElements())\r
416       {\r
417         String name = st.nextToken();\r
418         int start = Integer.parseInt(st.nextToken());\r
419         int end = Integer.parseInt(st.nextToken());\r
420         Sequence sequence = new Sequence(name, st.nextToken(), start, end);\r
421 \r
422         if (!newAlignment)\r
423         {\r
424           viewport.alignment.addSequence(sequence);\r
425         }\r
426         else\r
427         {\r
428           seqs.addElement(sequence);\r
429         }\r
430       }\r
431 \r
432       if (newAlignment)\r
433       {\r
434         SequenceI[] newSeqs = new SequenceI[seqs.size()];\r
435         for (int i = 0; i < seqs.size(); i++)\r
436         {\r
437           newSeqs[i] = (SequenceI) seqs.elementAt(i);\r
438         }\r
439 \r
440         String newtitle = new String("Copied sequences");\r
441         if (getTitle().startsWith("Copied sequences"))\r
442         {\r
443           newtitle = getTitle();\r
444         }\r
445         else\r
446         {\r
447           newtitle = newtitle.concat("- from " + getTitle());\r
448         }\r
449         AlignFrame af = new AlignFrame(new Alignment(newSeqs), applet, newtitle);\r
450 \r
451         jalview.bin.JalviewLite.addFrame(af, newtitle, NEW_WINDOW_WIDTH,\r
452                                          NEW_WINDOW_HEIGHT);\r
453       }\r
454       else\r
455       {\r
456         viewport.setEndSeq(viewport.alignment.getHeight());\r
457         viewport.alignment.getWidth();\r
458         viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
459       }\r
460 \r
461     }\r
462     catch (Exception ex)\r
463     {} // could be anything being pasted in here\r
464 \r
465   }\r
466 \r
467   protected void cut_actionPerformed(ActionEvent e)\r
468   {\r
469     copy_actionPerformed(null);\r
470     delete_actionPerformed(null);\r
471   }\r
472 \r
473   protected void delete_actionPerformed(ActionEvent e)\r
474   {\r
475     addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment,\r
476                                    HistoryItem.HIDE));\r
477     if (viewport.getSelectionGroup() == null)\r
478     {\r
479       return;\r
480     }\r
481 \r
482 \r
483     SequenceGroup sg = viewport.getSelectionGroup();\r
484     boolean allSequences = false;\r
485     if(sg.sequences.size()==viewport.alignment.getHeight())\r
486           allSequences = true;\r
487 \r
488     for (int i = 0; i < sg.sequences.size(); i++)\r
489     {\r
490       SequenceI seq = sg.getSequenceAt(i);\r
491       int index = viewport.getAlignment().findIndex(seq);\r
492       seq.deleteChars(sg.getStartRes(), sg.getEndRes() + 1);\r
493 \r
494       // If the cut affects all sequences, remove highlighted columns\r
495       if (allSequences)\r
496       {\r
497         viewport.getColumnSelection().removeElements(sg.getStartRes(),\r
498                                                      sg.getEndRes() + 1);\r
499       }\r
500 \r
501 \r
502       if (seq.getSequence().length() < 1)\r
503       {\r
504         viewport.getAlignment().deleteSequence(seq);\r
505       }\r
506       else\r
507       {\r
508         viewport.getAlignment().getSequences().setElementAt(seq, index);\r
509       }\r
510     }\r
511 \r
512     viewport.setSelectionGroup(null);\r
513     viewport.alignment.deleteGroup(sg);\r
514     viewport.resetSeqLimits(alignPanel.seqPanel.seqCanvas.getSize().height);\r
515     if (viewport.getAlignment().getHeight() < 1)\r
516     {\r
517       try\r
518       {\r
519         this.setVisible(false);\r
520       }\r
521       catch (Exception ex)\r
522       {}\r
523     }\r
524     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
525 \r
526   }\r
527 \r
528   protected void deleteGroups_actionPerformed(ActionEvent e)\r
529   {\r
530     viewport.alignment.deleteAllGroups();\r
531     viewport.setSelectionGroup(null);\r
532 \r
533     alignPanel.repaint();\r
534   }\r
535 \r
536   public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
537   {\r
538     SequenceGroup sg = new SequenceGroup();\r
539     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
540     {\r
541       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);\r
542     }\r
543     sg.setEndRes(viewport.alignment.getWidth()-1);\r
544     viewport.setSelectionGroup(sg);\r
545     alignPanel.repaint();\r
546     PaintRefresher.Refresh(null, viewport.alignment);\r
547   }\r
548 \r
549   public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
550   {\r
551     viewport.setSelectionGroup(null);\r
552     viewport.getColumnSelection().clear();\r
553     viewport.setSelectionGroup(null);\r
554     alignPanel.repaint();\r
555     PaintRefresher.Refresh(null, viewport.alignment);\r
556   }\r
557 \r
558   public void invertSequenceMenuItem_actionPerformed(ActionEvent e)\r
559   {\r
560     SequenceGroup sg = viewport.getSelectionGroup();\r
561     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
562     {\r
563       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);\r
564     }\r
565 \r
566     PaintRefresher.Refresh(null, viewport.alignment);\r
567   }\r
568 \r
569   public void remove2LeftMenuItem_actionPerformed(ActionEvent e)\r
570   {\r
571     ColumnSelection colSel = viewport.getColumnSelection();\r
572     if (colSel.size() > 0)\r
573     {\r
574       addHistoryItem(new HistoryItem("Remove Left", viewport.alignment,\r
575                                      HistoryItem.HIDE));\r
576       int min = colSel.getMin();\r
577       viewport.getAlignment().trimLeft(min);\r
578       colSel.compensateForEdit(0, min);\r
579 \r
580       if (viewport.getSelectionGroup() != null)\r
581       {\r
582         viewport.getSelectionGroup().adjustForRemoveLeft(min);\r
583       }\r
584 \r
585       Vector groups = viewport.alignment.getGroups();\r
586       for (int i = 0; i < groups.size(); i++)\r
587       {\r
588         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
589         if (!sg.adjustForRemoveLeft(min))\r
590         {\r
591           viewport.alignment.deleteGroup(sg);\r
592         }\r
593       }\r
594       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
595     }\r
596   }\r
597 \r
598   public void remove2RightMenuItem_actionPerformed(ActionEvent e)\r
599   {\r
600     ColumnSelection colSel = viewport.getColumnSelection();\r
601     if (colSel.size() > 0)\r
602     {\r
603       addHistoryItem(new HistoryItem("Remove Right", viewport.alignment,\r
604                                      HistoryItem.HIDE));\r
605       int max = colSel.getMax();\r
606       viewport.getAlignment().trimRight(max);\r
607       if (viewport.getSelectionGroup() != null)\r
608       {\r
609         viewport.getSelectionGroup().adjustForRemoveRight(max);\r
610       }\r
611 \r
612       Vector groups = viewport.alignment.getGroups();\r
613       for (int i = 0; i < groups.size(); i++)\r
614       {\r
615         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
616         if (!sg.adjustForRemoveRight(max))\r
617         {\r
618           viewport.alignment.deleteGroup(sg);\r
619         }\r
620       }\r
621       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
622     }\r
623 \r
624   }\r
625 \r
626   public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)\r
627   {\r
628     addHistoryItem(new HistoryItem("Remove Gapped Columns",\r
629                                    viewport.alignment,\r
630                                    HistoryItem.HIDE));\r
631 \r
632     //This is to maintain viewport position on first residue\r
633     //of first sequence\r
634     SequenceI seq = viewport.alignment.getSequenceAt(0);\r
635     int startRes = seq.findPosition(viewport.startRes);\r
636 \r
637     viewport.getAlignment().removeGaps();\r
638 \r
639     viewport.setStartRes(seq.findIndex(startRes)-1);\r
640 \r
641     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
642   }\r
643 \r
644   public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)\r
645   {\r
646     addHistoryItem(new HistoryItem("Remove Gaps", viewport.alignment,\r
647                                    HistoryItem.HIDE));\r
648 \r
649     //This is to maintain viewport position on first residue\r
650     //of first sequence\r
651     SequenceI seq = viewport.alignment.getSequenceAt(0);\r
652     int startRes = seq.findPosition(viewport.startRes);\r
653 \r
654     SequenceI current;\r
655     int jSize;\r
656 \r
657     Vector seqs=null;\r
658 \r
659     int start=0, end = viewport.alignment.getWidth();\r
660 \r
661     if (viewport.getSelectionGroup() != null\r
662         && viewport.getSelectionGroup().sequences != null\r
663         && viewport.getSelectionGroup().sequences.size()>0)\r
664     {\r
665       seqs = viewport.getSelectionGroup().sequences;\r
666       start = viewport.getSelectionGroup().getStartRes();\r
667       end = viewport.getSelectionGroup().getEndRes()+1;\r
668     }\r
669     else\r
670       seqs = viewport.alignment.getSequences();\r
671 \r
672     for (int i = 0; i < seqs.size(); i++)\r
673     {\r
674       current = (SequenceI) seqs.elementAt(i);\r
675       jSize = current.getLength();\r
676 \r
677       // Removing a range is much quicker than removing gaps\r
678       // one by one for long sequences\r
679       int j = start;\r
680       int rangeStart=-1, rangeEnd=-1;\r
681 \r
682       do\r
683       {\r
684         if (jalview.util.Comparison.isGap(current.getCharAt(j)))\r
685         {\r
686           if(rangeStart==-1)\r
687            {\r
688              rangeStart = j;\r
689              rangeEnd = j+1;\r
690            }\r
691            else\r
692            {\r
693              rangeEnd++;\r
694            }\r
695            j++;\r
696         }\r
697         else\r
698         {\r
699           if(rangeStart>-1)\r
700           {\r
701             current.deleteChars(rangeStart, rangeEnd);\r
702             j-=rangeEnd-rangeStart;\r
703             jSize-=rangeEnd-rangeStart;\r
704             rangeStart = -1;\r
705             rangeEnd = -1;\r
706           }\r
707           else\r
708             j++;\r
709         }\r
710       }\r
711       while (j < end && j < jSize);\r
712       if(rangeStart>-1)\r
713       {\r
714        current.deleteChars(rangeStart, rangeEnd);\r
715       }\r
716     }\r
717     viewport.setStartRes(seq.findIndex(startRes)-1);\r
718     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
719   }\r
720 \r
721   public void alignmentChanged()\r
722   {\r
723     viewport.updateConsensus();\r
724     viewport.updateConservation ();\r
725     resetAllColourSchemes();\r
726     if(alignPanel.overviewPanel!=null)\r
727       alignPanel.overviewPanel.updateOverviewImage();\r
728     alignPanel.repaint();\r
729   }\r
730 \r
731   void resetAllColourSchemes()\r
732   {\r
733     ColourSchemeI cs = viewport.globalColourScheme;\r
734     if(cs!=null)\r
735     {\r
736       if (cs instanceof ClustalxColourScheme)\r
737       {\r
738         ( (ClustalxColourScheme) viewport.getGlobalColourScheme()).\r
739             resetClustalX(viewport.alignment.getSequences(),\r
740                           viewport.alignment.getWidth());\r
741       }\r
742 \r
743       cs.setConsensus(viewport.vconsensus);\r
744       if (cs.conservationApplied())\r
745       {\r
746         Alignment al = (Alignment) viewport.alignment;\r
747         Conservation c = new Conservation("All",\r
748                                           ResidueProperties.propHash, 3,\r
749                                           al.getSequences(), 0,\r
750                                           al.getWidth() - 1);\r
751         c.calculate();\r
752         c.verdict(false, viewport.ConsPercGaps);\r
753 \r
754         cs.setConservation(c);\r
755       }\r
756     }\r
757 \r
758     int s, sSize = viewport.alignment.getGroups().size();\r
759     for(s=0; s<sSize; s++)\r
760     {\r
761       SequenceGroup sg = (SequenceGroup)viewport.alignment.getGroups().elementAt(s);\r
762       if(sg.cs!=null && sg.cs instanceof ClustalxColourScheme)\r
763       {\r
764         ((ClustalxColourScheme)sg.cs).resetClustalX(sg.sequences, sg.getWidth());\r
765       }\r
766       sg.recalcConservation();\r
767     }\r
768   }\r
769 \r
770 \r
771 \r
772   public void findMenuItem_actionPerformed(ActionEvent e)\r
773   {\r
774     Finder finder = new Finder(alignPanel);\r
775   }\r
776 \r
777   public void font_actionPerformed(ActionEvent e)\r
778   {\r
779     new FontChooser(alignPanel);\r
780   }\r
781 \r
782   protected void fullSeqId_actionPerformed(ActionEvent e)\r
783   {\r
784     viewport.setShowFullId(fullSeqId.getState());\r
785     alignPanel.fontChanged();\r
786     alignPanel.repaint();\r
787   }\r
788 \r
789   protected void colourTextMenuItem_actionPerformed(ActionEvent e)\r
790   {\r
791     viewport.setColourText(colourTextMenuItem.getState());\r
792     alignPanel.repaint();\r
793   }\r
794 \r
795   protected void wrapMenuItem_actionPerformed(ActionEvent e)\r
796   {\r
797     viewport.setWrapAlignment(wrapMenuItem.getState());\r
798     alignPanel.setWrapAlignment(wrapMenuItem.getState());\r
799     scaleAbove.setEnabled(wrapMenuItem.getState());\r
800     scaleLeft.setEnabled(wrapMenuItem.getState());\r
801     scaleRight.setEnabled(wrapMenuItem.getState());\r
802     alignPanel.repaint();\r
803   }\r
804 \r
805   protected void scaleAbove_actionPerformed(ActionEvent e)\r
806   {\r
807     viewport.setScaleAboveWrapped(scaleAbove.getState());\r
808     alignPanel.repaint();\r
809   }\r
810 \r
811   protected void scaleLeft_actionPerformed(ActionEvent e)\r
812   {\r
813     viewport.setScaleLeftWrapped(scaleLeft.getState());\r
814     alignPanel.repaint();\r
815   }\r
816 \r
817   protected void scaleRight_actionPerformed(ActionEvent e)\r
818   {\r
819     viewport.setScaleRightWrapped(scaleRight.getState());\r
820     alignPanel.repaint();\r
821   }\r
822 \r
823   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)\r
824   {\r
825     viewport.setShowBoxes(viewBoxesMenuItem.getState());\r
826     alignPanel.repaint();\r
827   }\r
828 \r
829   public void viewTextMenuItem_actionPerformed(ActionEvent e)\r
830   {\r
831     viewport.setShowText(viewTextMenuItem.getState());\r
832     alignPanel.repaint();\r
833   }\r
834 \r
835   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)\r
836   {\r
837     viewport.setRenderGaps(renderGapsMenuItem.getState());\r
838     alignPanel.repaint();\r
839   }\r
840 \r
841   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)\r
842   {\r
843     viewport.setShowAnnotation(annotationPanelMenuItem.getState());\r
844     alignPanel.setAnnotationVisible(annotationPanelMenuItem.getState());\r
845   }\r
846 \r
847   public void overviewMenuItem_actionPerformed(ActionEvent e)\r
848   {\r
849     if (alignPanel.overviewPanel != null)\r
850     {\r
851       return;\r
852     }\r
853 \r
854     Frame frame = new Frame();\r
855     OverviewPanel overview = new OverviewPanel(alignPanel);\r
856     frame.add(overview);\r
857     // +50 must allow for applet frame window\r
858     jalview.bin.JalviewLite.addFrame(frame, "Overview " + this.getTitle(),\r
859                                      overview.preferredSize().width,\r
860                                      overview.preferredSize().height + 50);\r
861 \r
862     frame.pack();\r
863     frame.addWindowListener(new WindowAdapter()\r
864     {\r
865       public void windowClosing(WindowEvent e)\r
866       {\r
867         alignPanel.setOverviewPanel(null);\r
868       };\r
869     });\r
870 \r
871     alignPanel.setOverviewPanel(overview);\r
872 \r
873   }\r
874 \r
875   protected void noColourmenuItem_actionPerformed(ActionEvent e)\r
876   {\r
877     changeColour(null);\r
878   }\r
879 \r
880   public void clustalColour_actionPerformed(ActionEvent e)\r
881   {\r
882     abovePIDThreshold.setState(false);\r
883     changeColour(new ClustalxColourScheme(viewport.alignment.getSequences(),\r
884                                           viewport.alignment.getWidth()));\r
885   }\r
886 \r
887   public void zappoColour_actionPerformed(ActionEvent e)\r
888   {\r
889     changeColour(new ZappoColourScheme());\r
890   }\r
891 \r
892   public void taylorColour_actionPerformed(ActionEvent e)\r
893   {\r
894     changeColour(new TaylorColourScheme());\r
895   }\r
896 \r
897   public void hydrophobicityColour_actionPerformed(ActionEvent e)\r
898   {\r
899     changeColour(new HydrophobicColourScheme());\r
900   }\r
901 \r
902   public void helixColour_actionPerformed(ActionEvent e)\r
903   {\r
904     changeColour(new HelixColourScheme());\r
905   }\r
906 \r
907   public void strandColour_actionPerformed(ActionEvent e)\r
908   {\r
909     changeColour(new StrandColourScheme());\r
910   }\r
911 \r
912   public void turnColour_actionPerformed(ActionEvent e)\r
913   {\r
914     changeColour(new TurnColourScheme());\r
915   }\r
916 \r
917   public void buriedColour_actionPerformed(ActionEvent e)\r
918   {\r
919     changeColour(new BuriedColourScheme());\r
920   }\r
921 \r
922   public void nucleotideColour_actionPerformed(ActionEvent e)\r
923   {\r
924     changeColour(new NucleotideColourScheme());\r
925   }\r
926 \r
927   protected void applyToAllGroups_actionPerformed(ActionEvent e)\r
928   {\r
929     viewport.setColourAppliesToAllGroups(applyToAllGroups.getState());\r
930   }\r
931 \r
932   void changeColour(ColourSchemeI cs)\r
933   {\r
934     int threshold = 0;\r
935 \r
936     if(cs!=null)\r
937     {\r
938       if (viewport.getAbovePIDThreshold())\r
939       {\r
940         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs, "Background");\r
941 \r
942         cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());\r
943 \r
944         viewport.setGlobalColourScheme(cs);\r
945       }\r
946       else\r
947       {\r
948         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
949       }\r
950 \r
951       if (viewport.getConservationSelected())\r
952       {\r
953 \r
954         Alignment al = (Alignment) viewport.alignment;\r
955         Conservation c = new Conservation("All",\r
956                                           ResidueProperties.propHash, 3,\r
957                                           al.getSequences(), 0,\r
958                                           al.getWidth() - 1);\r
959 \r
960         c.calculate();\r
961         c.verdict(false, viewport.ConsPercGaps);\r
962 \r
963         cs.setConservation(c);\r
964 \r
965         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,\r
966             "Background"));\r
967 \r
968       }\r
969       else\r
970       {\r
971         cs.setConservation(null);\r
972       }\r
973 \r
974       cs.setConsensus(viewport.vconsensus);\r
975 \r
976     }\r
977     viewport.setGlobalColourScheme(cs);\r
978 \r
979     if (viewport.getColourAppliesToAllGroups())\r
980     {\r
981       Vector groups = viewport.alignment.getGroups();\r
982       for (int i = 0; i < groups.size(); i++)\r
983       {\r
984         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
985 \r
986         if(cs==null)\r
987         {\r
988           sg.cs = null;\r
989           continue;\r
990         }\r
991         if (cs instanceof ClustalxColourScheme)\r
992         {\r
993           sg.cs = new ClustalxColourScheme(sg.sequences, sg.getWidth());\r
994         }\r
995         else\r
996         {\r
997           try\r
998           {\r
999             sg.cs = (ColourSchemeI) cs.getClass().newInstance();\r
1000           }\r
1001           catch (Exception ex)\r
1002           {\r
1003             ex.printStackTrace();\r
1004             sg.cs = cs;\r
1005           }\r
1006         }\r
1007 \r
1008         if (viewport.getAbovePIDThreshold()\r
1009             || cs instanceof PIDColourScheme\r
1010             || cs instanceof Blosum62ColourScheme)\r
1011         {\r
1012           sg.cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());\r
1013           sg.cs.setConsensus(AAFrequency.calculate(sg.sequences, 0, sg.getWidth()));\r
1014         }\r
1015         else\r
1016           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
1017 \r
1018         if (viewport.getConservationSelected())\r
1019         {\r
1020           Conservation c = new Conservation("Group",\r
1021                                             ResidueProperties.propHash, 3,\r
1022                                             sg.sequences, 0,\r
1023                                             viewport.alignment.getWidth() - 1);\r
1024           c.calculate();\r
1025           c.verdict(false, viewport.ConsPercGaps);\r
1026           sg.cs.setConservation(c);\r
1027         }\r
1028         else\r
1029         {\r
1030           sg.cs.setConservation(null);\r
1031           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
1032         }\r
1033 \r
1034       }\r
1035     }\r
1036 \r
1037 \r
1038     if (alignPanel.getOverviewPanel() != null)\r
1039     {\r
1040       alignPanel.getOverviewPanel().updateOverviewImage();\r
1041     }\r
1042 \r
1043     alignPanel.repaint();\r
1044   }\r
1045 \r
1046 \r
1047 \r
1048   protected void modifyPID_actionPerformed(ActionEvent e)\r
1049   {\r
1050     if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme!=null)\r
1051     {\r
1052       SliderPanel.setPIDSliderSource(alignPanel, viewport.getGlobalColourScheme(),\r
1053                                      "Background");\r
1054       SliderPanel.showPIDSlider();\r
1055     }\r
1056   }\r
1057 \r
1058   protected void modifyConservation_actionPerformed(ActionEvent e)\r
1059   {\r
1060     if (viewport.getConservationSelected() && viewport.globalColourScheme!=null)\r
1061     {\r
1062       SliderPanel.setConservationSlider(alignPanel, viewport.globalColourScheme,\r
1063                                         "Background");\r
1064       SliderPanel.showConservationSlider();\r
1065     }\r
1066   }\r
1067 \r
1068   protected void conservationMenuItem_actionPerformed(ActionEvent e)\r
1069   {\r
1070     viewport.setConservationSelected(conservationMenuItem.getState());\r
1071 \r
1072     viewport.setAbovePIDThreshold(false);\r
1073     abovePIDThreshold.setState(false);\r
1074 \r
1075     changeColour(viewport.getGlobalColourScheme());\r
1076 \r
1077     modifyConservation_actionPerformed(null);\r
1078   }\r
1079 \r
1080   public void abovePIDThreshold_actionPerformed(ActionEvent e)\r
1081   {\r
1082     viewport.setAbovePIDThreshold(abovePIDThreshold.getState());\r
1083 \r
1084     conservationMenuItem.setState(false);\r
1085     viewport.setConservationSelected(false);\r
1086 \r
1087     changeColour(viewport.getGlobalColourScheme());\r
1088 \r
1089     modifyPID_actionPerformed(null);\r
1090   }\r
1091 \r
1092   public void userDefinedColour_actionPerformed(ActionEvent e)\r
1093   {\r
1094     UserDefinedColours chooser = new UserDefinedColours(alignPanel, null);\r
1095   }\r
1096 \r
1097   public void PIDColour_actionPerformed(ActionEvent e)\r
1098   {\r
1099     changeColour(new PIDColourScheme());\r
1100   }\r
1101 \r
1102   public void BLOSUM62Colour_actionPerformed(ActionEvent e)\r
1103   {\r
1104     changeColour(new Blosum62ColourScheme());\r
1105   }\r
1106 \r
1107   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)\r
1108   {\r
1109     addHistoryItem(new HistoryItem("Pairwise Sort", viewport.alignment,\r
1110                                    HistoryItem.SORT));\r
1111     AlignmentSorter.sortByPID(viewport.getAlignment(),\r
1112                               viewport.getAlignment().getSequenceAt(0));\r
1113     alignPanel.repaint();\r
1114   }\r
1115 \r
1116   public void sortIDMenuItem_actionPerformed(ActionEvent e)\r
1117   {\r
1118     addHistoryItem(new HistoryItem("ID Sort", viewport.alignment,\r
1119                                    HistoryItem.SORT));\r
1120     AlignmentSorter.sortByID(viewport.getAlignment());\r
1121     alignPanel.repaint();\r
1122   }\r
1123 \r
1124   public void sortGroupMenuItem_actionPerformed(ActionEvent e)\r
1125   {\r
1126     addHistoryItem(new HistoryItem("Group Sort", viewport.alignment,\r
1127                                    HistoryItem.SORT));\r
1128     AlignmentSorter.sortByGroup(viewport.getAlignment());\r
1129     alignPanel.repaint();\r
1130 \r
1131   }\r
1132 \r
1133   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)\r
1134   {\r
1135     RedundancyPanel sp = new RedundancyPanel(alignPanel);\r
1136     Frame frame = new Frame();\r
1137     frame.add(sp);\r
1138     jalview.bin.JalviewLite.addFrame(frame, "Redundancy threshold selection",\r
1139                                      400, 120);\r
1140 \r
1141   }\r
1142 \r
1143   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)\r
1144   {\r
1145     if (viewport.getSelectionGroup().getSize() > 1)\r
1146     {\r
1147       Frame frame = new Frame();\r
1148       frame.add(new PairwiseAlignPanel(alignPanel));\r
1149       jalview.bin.JalviewLite.addFrame(frame, "Pairwise Alignment", 600, 500);\r
1150     }\r
1151   }\r
1152 \r
1153   public void PCAMenuItem_actionPerformed(ActionEvent e)\r
1154   {\r
1155     //are the sequences aligned?\r
1156     if (!viewport.alignment.isAligned())\r
1157     {\r
1158       SequenceI current;\r
1159       int Width = viewport.getAlignment().getWidth();\r
1160 \r
1161       for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
1162            i++)\r
1163       {\r
1164         current = viewport.getAlignment().getSequenceAt(i);\r
1165 \r
1166         if (current.getLength() < Width)\r
1167         {\r
1168           current.insertCharAt(Width - 1, viewport.getGapCharacter());\r
1169         }\r
1170       }\r
1171       alignPanel.repaint();\r
1172     }\r
1173 \r
1174     if ( (viewport.getSelectionGroup() != null &&\r
1175           viewport.getSelectionGroup().getSize() < 4 &&\r
1176           viewport.getSelectionGroup().getSize() > 0)\r
1177         || viewport.getAlignment().getHeight() < 4)\r
1178     {\r
1179       return;\r
1180     }\r
1181 \r
1182     try\r
1183     {\r
1184       new PCAPanel(viewport);\r
1185     }\r
1186     catch (java.lang.OutOfMemoryError ex)\r
1187     {\r
1188     }\r
1189 \r
1190   }\r
1191 \r
1192   public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)\r
1193   {\r
1194     NewTreePanel("AV", "PID", "Average distance tree using PID");\r
1195   }\r
1196 \r
1197   public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)\r
1198   {\r
1199     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");\r
1200   }\r
1201 \r
1202   protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
1203   {\r
1204     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");\r
1205   }\r
1206 \r
1207   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
1208   {\r
1209     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62PID");\r
1210   }\r
1211 \r
1212   void NewTreePanel(String type, String pwType, String title)\r
1213   {\r
1214     //are the sequences aligned?\r
1215     if (!viewport.alignment.isAligned())\r
1216     {\r
1217       SequenceI current;\r
1218       int Width = viewport.getAlignment().getWidth();\r
1219 \r
1220       for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
1221            i++)\r
1222       {\r
1223         current = viewport.getAlignment().getSequenceAt(i);\r
1224 \r
1225         if (current.getLength() < Width)\r
1226         {\r
1227           current.insertCharAt(Width - 1, viewport.getGapCharacter());\r
1228         }\r
1229       }\r
1230       alignPanel.repaint();\r
1231 \r
1232     }\r
1233 \r
1234     final TreePanel tp;\r
1235     if (viewport.getSelectionGroup() != null &&\r
1236         viewport.getSelectionGroup().getSize() > 3)\r
1237     {\r
1238       tp = new TreePanel(viewport, viewport.getSelectionGroup().sequences, type,\r
1239                          pwType,\r
1240                          0, viewport.alignment.getWidth());\r
1241     }\r
1242     else\r
1243     {\r
1244       tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),\r
1245                          type, pwType, 0, viewport.alignment.getWidth());\r
1246     }\r
1247 \r
1248     addTreeMenuItem(tp, title);\r
1249 \r
1250     jalview.bin.JalviewLite.addFrame(tp, title, 600, 500);\r
1251   }\r
1252 \r
1253   void addTreeMenuItem(final TreePanel treePanel, String title)\r
1254   {\r
1255     final MenuItem item = new MenuItem(title);\r
1256     sortByTreeMenu.add(item);\r
1257     item.addActionListener(new java.awt.event.ActionListener()\r
1258     {\r
1259       public void actionPerformed(ActionEvent e)\r
1260       {\r
1261         addHistoryItem(new HistoryItem("Sort", viewport.alignment,\r
1262                                        HistoryItem.SORT));\r
1263         AlignmentSorter.sortByTree(viewport.getAlignment(), treePanel.getTree());\r
1264         alignPanel.repaint();\r
1265       }\r
1266     });\r
1267 \r
1268     treePanel.addWindowListener(new WindowAdapter()\r
1269     {\r
1270       public void windowClosing(WindowEvent e)\r
1271       {\r
1272         sortByTreeMenu.remove(item);\r
1273       };\r
1274     });\r
1275   }\r
1276 \r
1277   protected void documentation_actionPerformed(ActionEvent e)\r
1278   {\r
1279     jalview.bin.JalviewLite.showURL("http://www.jalview.org/help.html");\r
1280   }\r
1281 \r
1282   protected void about_actionPerformed(ActionEvent e)\r
1283   {\r
1284 \r
1285     class AboutPanel extends Canvas\r
1286     {\r
1287       String version;\r
1288       public AboutPanel(String version)\r
1289       { this.version = version; }\r
1290 \r
1291       public void paint(Graphics g)\r
1292       {\r
1293         g.setColor(Color.white);\r
1294         g.fillRect(0, 0, getSize().width, getSize().height);\r
1295         g.setFont(new Font("Helvetica", Font.PLAIN, 12));\r
1296         FontMetrics fm = g.getFontMetrics();\r
1297         int fh = fm.getHeight();\r
1298         int y = 5, x = 7;\r
1299         g.setColor(Color.black);\r
1300         g.setFont(new Font("Helvetica", Font.BOLD, 14));\r
1301         g.drawString("Jalview - Release "+version, 200, y += fh);\r
1302         g.setFont(new Font("Helvetica", Font.PLAIN, 12));\r
1303         g.drawString("Authors:  Michele Clamp, James Cuff, Steve Searle, Andrew Waterhouse, Jim Procter & Geoff Barton.",\r
1304                      x, y += fh * 2);\r
1305         g.drawString("Current development managed by Andrew Waterhouse; Barton Group, University of Dundee.",\r
1306                      x, y += fh);\r
1307         g.drawString(\r
1308             "For any issues relating to Jalview, email help@jalview.org", x,\r
1309             y += fh);\r
1310         g.drawString("If  you use JalView, please cite:", x, y += fh + 8);\r
1311         g.drawString("\"Clamp, M., Cuff, J., Searle, S. M. and Barton, G. J. (2004), The Jalview Java Alignment Editor\"",\r
1312                      x, y += fh);\r
1313         g.drawString("Bioinformatics,  2004 12;426-7.", x, y += fh);\r
1314       }\r
1315     }\r
1316 \r
1317     String version = "test";\r
1318     java.net.URL url = getClass().getResource("/.build_properties");\r
1319     if (url != null)\r
1320     {\r
1321       try\r
1322       {\r
1323         BufferedReader reader = new BufferedReader(new InputStreamReader(\r
1324             url.openStream()));\r
1325         String line;\r
1326         while ( (line = reader.readLine()) != null)\r
1327         {\r
1328           if (line.indexOf("VERSION") > -1)\r
1329           {\r
1330             version = line.substring(line.indexOf("=") + 1);\r
1331           }\r
1332         }\r
1333       }\r
1334       catch (Exception ex)\r
1335       {\r
1336         ex.printStackTrace();\r
1337       }\r
1338     }\r
1339 \r
1340 \r
1341     Frame frame = new Frame();\r
1342     frame.add(new AboutPanel(version));\r
1343     jalview.bin.JalviewLite.addFrame(frame, "Jalview", 580, 200);\r
1344 \r
1345   }\r
1346 }\r