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