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