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