Remove gaps in regions, not char by char
[jalview.git] / src / jalview / gui / 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 Softwarechang\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import java.beans.*;\r
22 import java.io.*;\r
23 import java.util.*;\r
24 \r
25 import java.awt.*;\r
26 import java.awt.datatransfer.*;\r
27 import java.awt.event.*;\r
28 import java.awt.print.*;\r
29 import javax.swing.*;\r
30 import javax.swing.event.*;\r
31 \r
32 import jalview.analysis.*;\r
33 import jalview.datamodel.*;\r
34 import jalview.io.*;\r
35 import jalview.jbgui.*;\r
36 import jalview.schemes.*;\r
37 import jalview.ws.*;\r
38 \r
39 /**\r
40  * DOCUMENT ME!\r
41  *\r
42  * @author $author$\r
43  * @version $Revision$\r
44  */\r
45 public class AlignFrame\r
46     extends GAlignFrame\r
47 {\r
48   /** DOCUMENT ME!! */\r
49   public static final int NEW_WINDOW_WIDTH = 700;\r
50 \r
51   /** DOCUMENT ME!! */\r
52   public static final int NEW_WINDOW_HEIGHT = 500;\r
53   final AlignmentPanel alignPanel;\r
54   final AlignViewport viewport;\r
55 \r
56   /** DOCUMENT ME!! */\r
57   public String currentFileFormat = null;\r
58   Stack historyList = new Stack();\r
59   Stack redoList = new Stack();\r
60   private int treeCount = 0;\r
61 \r
62   /**\r
63    * Creates a new AlignFrame object.\r
64    *\r
65    * @param al DOCUMENT ME!\r
66    */\r
67   public AlignFrame(AlignmentI al)\r
68   {\r
69     viewport = new AlignViewport(al);\r
70 \r
71     if(viewport.vconsensus==null)\r
72     {\r
73       //Out of memory caluclating consensus.\r
74       BLOSUM62Colour.setEnabled(false);\r
75       PIDColour.setEnabled(false);\r
76       conservationMenuItem.setEnabled(false);\r
77       modifyConservation.setEnabled(false);\r
78       abovePIDThreshold.setEnabled(false);\r
79       modifyPID.setEnabled(false);\r
80     }\r
81 \r
82     alignPanel = new AlignmentPanel(this, viewport);\r
83     alignPanel.annotationPanel.adjustPanelHeight();\r
84     alignPanel.annotationSpaceFillerHolder.setPreferredSize(alignPanel.\r
85         annotationPanel.getPreferredSize());\r
86     alignPanel.annotationScroller.setPreferredSize(alignPanel.annotationPanel.\r
87         getPreferredSize());\r
88     alignPanel.setAnnotationVisible(viewport.getShowAnnotation());\r
89 \r
90     String sortby = jalview.bin.Cache.getDefault("SORT_ALIGNMENT", "No sort");\r
91 \r
92     if(sortby.equals("Id"))\r
93       sortIDMenuItem_actionPerformed(null);\r
94     else if(sortby.equals("Pairwise Identity"))\r
95       sortPairwiseMenuItem_actionPerformed(null);\r
96 \r
97     getContentPane().add(alignPanel, java.awt.BorderLayout.CENTER);\r
98 \r
99     viewport.addPropertyChangeListener(new PropertyChangeListener()\r
100     {\r
101      public void propertyChange(PropertyChangeEvent evt)\r
102      {\r
103        if (evt.getPropertyName().equals("alignment"))\r
104        {\r
105          alignmentChanged();\r
106        }\r
107      }\r
108    });\r
109 \r
110 \r
111     addServiceListeners();\r
112   }\r
113 \r
114   /* Set up intrinsic listeners for dynamically generated GUI bits. */\r
115   private void addServiceListeners()\r
116   {\r
117     final java.beans.PropertyChangeListener thisListener;\r
118     // Do this once to get current state\r
119     BuildWebServiceMenu();\r
120     Desktop.discoverer.addPropertyChangeListener(\r
121         thisListener = new java.beans.PropertyChangeListener()\r
122     {\r
123       public void propertyChange(PropertyChangeEvent evt)\r
124       {\r
125         // System.out.println("Discoverer property change.");\r
126         if (evt.getPropertyName().equals("services"))\r
127         {\r
128           // System.out.println("Rebuilding web service menu");\r
129           BuildWebServiceMenu();\r
130         }\r
131       }\r
132     });\r
133     addInternalFrameListener(new javax.swing.event.\r
134                              InternalFrameAdapter()\r
135     {\r
136       public void internalFrameClosed(\r
137           javax.swing.event.InternalFrameEvent evt)\r
138       {\r
139         // System.out.println("deregistering discoverer listener");\r
140         Desktop.discoverer.removePropertyChangeListener(thisListener);\r
141         closeMenuItem_actionPerformed(null);\r
142       }\r
143       ;\r
144     });\r
145 \r
146   }\r
147 \r
148   /**\r
149    * DOCUMENT ME!\r
150    *\r
151    * @param String DOCUMENT ME!\r
152    */\r
153 \r
154   public void parseGroupsFile(String file)\r
155   {\r
156     try\r
157     {\r
158       BufferedReader in = new BufferedReader(new FileReader(file));\r
159       SequenceI seq = null;\r
160       String line, text, token;\r
161       UserColourScheme ucs;\r
162       int index, start, end;\r
163       StringTokenizer st;\r
164       SequenceGroup sg;\r
165       while ( (line = in.readLine()) != null)\r
166       {\r
167         st = new StringTokenizer(line, "\t");\r
168         if (st.countTokens() != 6)\r
169         {\r
170           System.out.println("Groups file " + file +\r
171                              " is invalid. Read help file.");\r
172           System.exit(1);\r
173         }\r
174 \r
175         while (st.hasMoreElements())\r
176         {\r
177           text = st.nextToken();\r
178           token = st.nextToken();\r
179           if (!token.equals("ID_NOT_SPECIFIED"))\r
180           {\r
181             index = viewport.alignment.findIndex(viewport.alignment.findName(\r
182                 token));\r
183             st.nextToken();\r
184           }\r
185           else\r
186           {\r
187             index = Integer.parseInt(st.nextToken());\r
188           }\r
189 \r
190           start = Integer.parseInt(st.nextToken());\r
191           end = Integer.parseInt(st.nextToken());\r
192           ucs = new UserColourScheme(st.nextToken());\r
193 \r
194           seq = viewport.alignment.getSequenceAt(index);\r
195           start = seq.findIndex(start) - 1;\r
196           end = seq.findIndex(end) - 1;\r
197 \r
198           sg = new SequenceGroup(text, ucs, true, true, false, start, end);\r
199           sg.addSequence(seq, true);\r
200 \r
201           viewport.alignment.addGroup(sg);\r
202         }\r
203       }\r
204 \r
205     }\r
206     catch (Exception ex)\r
207     {\r
208       System.out.println("Error parsing groups file: " + ex);\r
209     }\r
210   }\r
211 \r
212   /**\r
213    * DOCUMENT ME!\r
214    *\r
215    * @param e DOCUMENT ME!\r
216    */\r
217   public void saveAlignmentMenu_actionPerformed(ActionEvent e)\r
218   {\r
219     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.\r
220         getProperty(\r
221             "LAST_DIRECTORY"),\r
222         new String[]\r
223         {\r
224         "fa, fasta, fastq", "aln", "pfam", "msf", "pir", "blc",\r
225         "jar"\r
226     },\r
227         new String[]\r
228         {\r
229         "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview"\r
230     }, currentFileFormat);\r
231 \r
232     chooser.setAcceptAllFileFilterUsed(false);\r
233     chooser.setFileView(new JalviewFileView());\r
234     chooser.setDialogTitle("Save Alignment to file");\r
235     chooser.setToolTipText("Save");\r
236 \r
237     int value = chooser.showSaveDialog(this);\r
238 \r
239     if (value == JalviewFileChooser.APPROVE_OPTION)\r
240     {\r
241       currentFileFormat = chooser.getSelectedFormat();\r
242       jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT",\r
243                                     currentFileFormat);\r
244 \r
245       String choice = chooser.getSelectedFile().getPath();\r
246       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);\r
247 \r
248       saveAlignment(choice, currentFileFormat);\r
249     }\r
250   }\r
251 \r
252   public boolean saveAlignment(String file, String format)\r
253   {\r
254     if (format.equalsIgnoreCase("Jalview"))\r
255     {\r
256       String shortName = title;\r
257 \r
258       if (shortName.indexOf(java.io.File.separatorChar) > -1)\r
259       {\r
260         shortName = shortName.substring(shortName.lastIndexOf(\r
261             java.io.File.separatorChar) + 1);\r
262       }\r
263 \r
264       Jalview2XML.SaveAlignment(this, file, shortName);\r
265 \r
266       // USE Jalview2XML to save this file\r
267       return true;\r
268     }\r
269     else\r
270     {\r
271       String output = FormatAdapter.formatSequences(format,\r
272           viewport.getAlignment().\r
273           getSequences());\r
274       if (output == null)\r
275       {\r
276         return false;\r
277       }\r
278 \r
279       try\r
280       {\r
281         java.io.PrintWriter out = new java.io.PrintWriter(\r
282             new java.io.FileWriter(file));\r
283 \r
284         out.print(output);\r
285         out.close();\r
286         return true;\r
287       }\r
288       catch (Exception ex)\r
289       {\r
290         ex.printStackTrace();\r
291       }\r
292     }\r
293     return false;\r
294   }\r
295 \r
296   /**\r
297    * DOCUMENT ME!\r
298    *\r
299    * @param e DOCUMENT ME!\r
300    */\r
301   protected void outputText_actionPerformed(ActionEvent e)\r
302   {\r
303     CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
304     Desktop.addInternalFrame(cap,\r
305                              "Alignment output - " + e.getActionCommand(), 600,\r
306                              500);\r
307     cap.setText(FormatAdapter.formatSequences(e.getActionCommand(),\r
308                                               viewport.getAlignment().\r
309                                               getSequences()));\r
310   }\r
311 \r
312   /**\r
313    * DOCUMENT ME!\r
314    *\r
315    * @param e DOCUMENT ME!\r
316    */\r
317   protected void htmlMenuItem_actionPerformed(ActionEvent e)\r
318   {\r
319     new HTMLOutput(viewport);\r
320   }\r
321 \r
322   public void createImageMap(File file, String image)\r
323   {\r
324     alignPanel.makePNGImageMap(file, image);\r
325   }\r
326 \r
327   /**\r
328    * DOCUMENT ME!\r
329    *\r
330    * @param e DOCUMENT ME!\r
331    */\r
332   public void createPNG(File f)\r
333   {\r
334     alignPanel.makePNG(f);\r
335   }\r
336 \r
337   /**\r
338    * DOCUMENT ME!\r
339    *\r
340    * @param e DOCUMENT ME!\r
341    */\r
342   public void createEPS(File f)\r
343   {\r
344     alignPanel.makeEPS(f);\r
345   }\r
346 \r
347   /**\r
348    * DOCUMENT ME!\r
349    *\r
350    * @param e DOCUMENT ME!\r
351    */\r
352   public void printMenuItem_actionPerformed(ActionEvent e)\r
353   {\r
354     //Putting in a thread avoids Swing painting problems\r
355     PrintThread thread = new PrintThread();\r
356     thread.start();\r
357   }\r
358 \r
359   /**\r
360    * DOCUMENT ME!\r
361    *\r
362    * @param e DOCUMENT ME!\r
363    */\r
364   public void closeMenuItem_actionPerformed(ActionEvent e)\r
365   {\r
366     try\r
367     {\r
368       PaintRefresher.components.remove(viewport.alignment);\r
369       this.setClosed(true);\r
370     }\r
371     catch (Exception ex)\r
372     {\r
373     }\r
374   }\r
375 \r
376   /**\r
377    * DOCUMENT ME!\r
378    */\r
379   void updateEditMenuBar()\r
380   {\r
381     if (historyList.size() > 0)\r
382     {\r
383       undoMenuItem.setEnabled(true);\r
384 \r
385       HistoryItem hi = (HistoryItem) historyList.peek();\r
386       undoMenuItem.setText("Undo " + hi.getDescription());\r
387     }\r
388     else\r
389     {\r
390       undoMenuItem.setEnabled(false);\r
391       undoMenuItem.setText("Undo");\r
392     }\r
393 \r
394     if (redoList.size() > 0)\r
395     {\r
396       redoMenuItem.setEnabled(true);\r
397 \r
398       HistoryItem hi = (HistoryItem) redoList.peek();\r
399       redoMenuItem.setText("Redo " + hi.getDescription());\r
400     }\r
401     else\r
402     {\r
403       redoMenuItem.setEnabled(false);\r
404       redoMenuItem.setText("Redo");\r
405     }\r
406   }\r
407 \r
408   /**\r
409    * DOCUMENT ME!\r
410    *\r
411    * @param hi DOCUMENT ME!\r
412    */\r
413   public void addHistoryItem(HistoryItem hi)\r
414   {\r
415     historyList.push(hi);\r
416     updateEditMenuBar();\r
417   }\r
418 \r
419   /**\r
420    * DOCUMENT ME!\r
421    *\r
422    * @param e DOCUMENT ME!\r
423    */\r
424   protected void undoMenuItem_actionPerformed(ActionEvent e)\r
425   {\r
426     HistoryItem hi = (HistoryItem) historyList.pop();\r
427     redoList.push(new HistoryItem(hi.getDescription(), viewport.alignment,\r
428                                   HistoryItem.HIDE));\r
429     restoreHistoryItem(hi);\r
430     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
431   }\r
432 \r
433   /**\r
434    * DOCUMENT ME!\r
435    *\r
436    * @param e DOCUMENT ME!\r
437    */\r
438   protected void redoMenuItem_actionPerformed(ActionEvent e)\r
439   {\r
440     HistoryItem hi = (HistoryItem) redoList.pop();\r
441     restoreHistoryItem(hi);\r
442     updateEditMenuBar();\r
443     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
444   }\r
445 \r
446   // used by undo and redo\r
447   void restoreHistoryItem(HistoryItem hi)\r
448   {\r
449     if (hi.getType() == HistoryItem.SORT)\r
450     {\r
451       for (int i = 0; i < hi.getSequences().size(); i++)\r
452       {\r
453         viewport.alignment.getSequences().setElementAt(hi.getSequences()\r
454             .elementAt(i),\r
455             i);\r
456       }\r
457     }\r
458     else\r
459     {\r
460       for (int i = 0; i < hi.getSequences().size(); i++)\r
461       {\r
462         SequenceI restore = (SequenceI) hi.getSequences().elementAt(i);\r
463 \r
464         if (restore.getLength() == 0)\r
465         {\r
466           restore.setSequence(hi.getHidden().elementAt(i).toString());\r
467           viewport.alignment.getSequences().insertElementAt(restore,\r
468               hi.getAlignIndex(i));\r
469         }\r
470         else\r
471         {\r
472           restore.setSequence(hi.getHidden().elementAt(i).toString());\r
473         }\r
474       }\r
475 \r
476       if (hi.getType() == HistoryItem.PASTE)\r
477       {\r
478         for (int i = viewport.alignment.getHeight() - 1;\r
479              i > (hi.getSequences().size() - 1); i--)\r
480         {\r
481           viewport.alignment.deleteSequence(i);\r
482         }\r
483       }\r
484     }\r
485 \r
486     updateEditMenuBar();\r
487 \r
488     viewport.firePropertyChange("alignment", null,\r
489                                 viewport.getAlignment().getSequences());\r
490   }\r
491 \r
492   /**\r
493    * DOCUMENT ME!\r
494    *\r
495    * @param up DOCUMENT ME!\r
496    */\r
497   public void moveSelectedSequences(boolean up)\r
498   {\r
499     SequenceGroup sg = viewport.getSelectionGroup();\r
500 \r
501     if (sg == null)\r
502     {\r
503       return;\r
504     }\r
505 \r
506     if (up)\r
507     {\r
508       for (int i = 1; i < viewport.alignment.getHeight(); i++)\r
509       {\r
510         SequenceI seq = viewport.alignment.getSequenceAt(i);\r
511 \r
512         if (!sg.sequences.contains(seq))\r
513         {\r
514           continue;\r
515         }\r
516 \r
517         SequenceI temp = viewport.alignment.getSequenceAt(i - 1);\r
518 \r
519         if (sg.sequences.contains(temp))\r
520         {\r
521           continue;\r
522         }\r
523 \r
524         viewport.alignment.getSequences().setElementAt(temp, i);\r
525         viewport.alignment.getSequences().setElementAt(seq, i - 1);\r
526       }\r
527     }\r
528     else\r
529     {\r
530       for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)\r
531       {\r
532         SequenceI seq = viewport.alignment.getSequenceAt(i);\r
533 \r
534         if (!sg.sequences.contains(seq))\r
535         {\r
536           continue;\r
537         }\r
538 \r
539         SequenceI temp = viewport.alignment.getSequenceAt(i + 1);\r
540 \r
541         if (sg.sequences.contains(temp))\r
542         {\r
543           continue;\r
544         }\r
545 \r
546         viewport.alignment.getSequences().setElementAt(temp, i);\r
547         viewport.alignment.getSequences().setElementAt(seq, i + 1);\r
548       }\r
549     }\r
550 \r
551     alignPanel.repaint();\r
552   }\r
553 \r
554   /**\r
555    * DOCUMENT ME!\r
556    *\r
557    * @param e DOCUMENT ME!\r
558    */\r
559   protected void copy_actionPerformed(ActionEvent e)\r
560   {\r
561     if (viewport.getSelectionGroup() == null)\r
562     {\r
563       return;\r
564     }\r
565 \r
566     SequenceGroup sg = viewport.getSelectionGroup();\r
567 \r
568     Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();\r
569     StringBuffer buffer = new StringBuffer();\r
570 \r
571     Hashtable orderedSeqs = new Hashtable();\r
572 \r
573     for (int i = 0; i < sg.getSize(); i++)\r
574     {\r
575       SequenceI seq = sg.getSequenceAt(i);\r
576       int index = viewport.alignment.findIndex(seq);\r
577       orderedSeqs.put(index + "", seq);\r
578     }\r
579 \r
580     int index = 0, startRes, endRes;\r
581     char ch;\r
582 \r
583     for (int i = 0; i < sg.getSize(); i++)\r
584     {\r
585       SequenceI seq = null;\r
586 \r
587       while (seq == null)\r
588       {\r
589         if (orderedSeqs.containsKey(index + ""))\r
590         {\r
591           seq = (SequenceI) orderedSeqs.get(index + "");\r
592           index++;\r
593 \r
594           break;\r
595         }\r
596         else\r
597         {\r
598           index++;\r
599         }\r
600       }\r
601       //FIND START RES\r
602       //Returns residue following index if gap\r
603       startRes = seq.findPosition(sg.getStartRes());\r
604 \r
605       //FIND END RES\r
606       //Need to find the residue preceeding index if gap\r
607       endRes = 0;\r
608 \r
609       for (int j = 0; j < sg.getEndRes() + 1 && j < seq.getLength(); j++)\r
610       {\r
611         ch = seq.getCharAt(j);\r
612         if (!jalview.util.Comparison.isGap( (ch)))\r
613         {\r
614           endRes++;\r
615         }\r
616       }\r
617 \r
618       if (endRes > 0)\r
619       {\r
620         endRes += seq.getStart() - 1;\r
621       }\r
622 \r
623       buffer.append(seq.getName() + "\t" +\r
624                     startRes + "\t" +\r
625                     endRes + "\t" +\r
626                     seq.getSequence(sg.getStartRes(),\r
627                                     sg.getEndRes() + 1) + "\n");\r
628     }\r
629 \r
630     c.setContents(new StringSelection(buffer.toString()), null);\r
631   }\r
632 \r
633   /**\r
634    * DOCUMENT ME!\r
635    *\r
636    * @param e DOCUMENT ME!\r
637    */\r
638   protected void pasteNew_actionPerformed(ActionEvent e)\r
639   {\r
640     paste(true);\r
641   }\r
642 \r
643   /**\r
644    * DOCUMENT ME!\r
645    *\r
646    * @param e DOCUMENT ME!\r
647    */\r
648   protected void pasteThis_actionPerformed(ActionEvent e)\r
649   {\r
650     addHistoryItem(new HistoryItem("Paste Sequences", viewport.alignment,\r
651                                    HistoryItem.PASTE));\r
652     paste(false);\r
653   }\r
654 \r
655   /**\r
656    * DOCUMENT ME!\r
657    *\r
658    * @param newAlignment DOCUMENT ME!\r
659    */\r
660   void paste(boolean newAlignment)\r
661   {\r
662     try\r
663     {\r
664       Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();\r
665       Transferable contents = c.getContents(this);\r
666 \r
667       if (contents == null)\r
668       {\r
669         return;\r
670       }\r
671 \r
672       String str = (String) contents.getTransferData(DataFlavor.stringFlavor);\r
673       StringTokenizer st = new StringTokenizer(str);\r
674       ArrayList seqs = new ArrayList();\r
675 \r
676       while (st.hasMoreElements())\r
677       {\r
678         String name = st.nextToken();\r
679         int start = Integer.parseInt(st.nextToken());\r
680         int end = Integer.parseInt(st.nextToken());\r
681         Sequence sequence = new Sequence(name, st.nextToken(), start,\r
682                                          end);\r
683 \r
684         if (!newAlignment)\r
685         {\r
686           viewport.alignment.addSequence(sequence);\r
687         }\r
688         else\r
689         {\r
690           seqs.add(sequence);\r
691         }\r
692       }\r
693 \r
694       if (newAlignment)\r
695       {\r
696         SequenceI[] newSeqs = new SequenceI[seqs.size()];\r
697         seqs.toArray(newSeqs);\r
698 \r
699         AlignFrame af = new AlignFrame(new Alignment(newSeqs));\r
700         String newtitle = new String("Copied sequences");\r
701 \r
702         if (title.startsWith("Copied sequences"))\r
703         {\r
704           newtitle = title;\r
705         }\r
706         else\r
707         {\r
708           newtitle = newtitle.concat("- from " + title);\r
709         }\r
710 \r
711         Desktop.addInternalFrame(af, newtitle, NEW_WINDOW_WIDTH,\r
712                                  NEW_WINDOW_HEIGHT);\r
713       }\r
714       else\r
715       {\r
716         viewport.setEndSeq(viewport.alignment.getHeight());\r
717         viewport.alignment.getWidth();\r
718         viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
719       }\r
720     }\r
721     catch (Exception ex)\r
722     {\r
723         // could be anything being pasted in here\r
724     }\r
725 \r
726 \r
727   }\r
728 \r
729   /**\r
730    * DOCUMENT ME!\r
731    *\r
732    * @param e DOCUMENT ME!\r
733    */\r
734   protected void cut_actionPerformed(ActionEvent e)\r
735   {\r
736     copy_actionPerformed(null);\r
737     delete_actionPerformed(null);\r
738   }\r
739 \r
740   /**\r
741    * DOCUMENT ME!\r
742    *\r
743    * @param e DOCUMENT ME!\r
744    */\r
745   protected void delete_actionPerformed(ActionEvent e)\r
746   {\r
747 \r
748     if (viewport.getSelectionGroup() == null)\r
749     {\r
750       return;\r
751     }\r
752 \r
753     addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment,\r
754                                    HistoryItem.HIDE));\r
755 \r
756     SequenceGroup sg = viewport.getSelectionGroup();\r
757     boolean allSequences = false;\r
758     if (sg.sequences.size() == viewport.alignment.getHeight())\r
759     {\r
760       allSequences = true;\r
761     }\r
762 \r
763     for (int i = 0; i < sg.sequences.size(); i++)\r
764     {\r
765       SequenceI seq = sg.getSequenceAt(i);\r
766       int index = viewport.getAlignment().findIndex(seq);\r
767       seq.deleteChars(sg.getStartRes(), sg.getEndRes() + 1);\r
768 \r
769       // If the cut affects all sequences, remove highlighted columns\r
770       if (allSequences)\r
771       {\r
772         viewport.getColumnSelection().removeElements(sg.getStartRes(),\r
773             sg.getEndRes() + 1);\r
774       }\r
775 \r
776       if (seq.getSequence().length() < 1)\r
777       {\r
778         viewport.getAlignment().deleteSequence(seq);\r
779       }\r
780       else\r
781       {\r
782         viewport.getAlignment().getSequences().setElementAt(seq, index);\r
783       }\r
784     }\r
785 \r
786     viewport.setSelectionGroup(null);\r
787     viewport.alignment.deleteGroup(sg);\r
788 \r
789     viewport.firePropertyChange("alignment", null,\r
790                                   viewport.getAlignment().getSequences());\r
791 \r
792 \r
793 \r
794     if (viewport.getAlignment().getHeight() < 1)\r
795     {\r
796       try\r
797       {\r
798         this.setClosed(true);\r
799       }\r
800       catch (Exception ex)\r
801       {\r
802       }\r
803     }\r
804   }\r
805 \r
806   /**\r
807    * DOCUMENT ME!\r
808    *\r
809    * @param e DOCUMENT ME!\r
810    */\r
811   protected void deleteGroups_actionPerformed(ActionEvent e)\r
812   {\r
813     viewport.alignment.deleteAllGroups();\r
814     viewport.setSelectionGroup(null);\r
815     alignPanel.repaint();\r
816   }\r
817 \r
818   /**\r
819    * DOCUMENT ME!\r
820    *\r
821    * @param e DOCUMENT ME!\r
822    */\r
823   public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
824   {\r
825     SequenceGroup sg = new SequenceGroup();\r
826 \r
827     for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
828          i++)\r
829     {\r
830       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);\r
831     }\r
832 \r
833     sg.setEndRes(viewport.alignment.getWidth() - 1);\r
834     viewport.setSelectionGroup(sg);\r
835     PaintRefresher.Refresh(null, viewport.alignment);\r
836   }\r
837 \r
838   /**\r
839    * DOCUMENT ME!\r
840    *\r
841    * @param e DOCUMENT ME!\r
842    */\r
843   public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
844   {\r
845     viewport.setSelectionGroup(null);\r
846     viewport.getColumnSelection().clear();\r
847     viewport.setSelectionGroup(null);\r
848     alignPanel.annotationPanel.activeRes = null;\r
849     PaintRefresher.Refresh(null, viewport.alignment);\r
850   }\r
851 \r
852   /**\r
853    * DOCUMENT ME!\r
854    *\r
855    * @param e DOCUMENT ME!\r
856    */\r
857   public void invertSequenceMenuItem_actionPerformed(ActionEvent e)\r
858   {\r
859     SequenceGroup sg = viewport.getSelectionGroup();\r
860 \r
861     if (sg == null)\r
862     {\r
863       selectAllSequenceMenuItem_actionPerformed(null);\r
864 \r
865       return;\r
866     }\r
867 \r
868     for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
869          i++)\r
870     {\r
871       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);\r
872     }\r
873 \r
874     PaintRefresher.Refresh(null, viewport.alignment);\r
875   }\r
876 \r
877   /**\r
878    * DOCUMENT ME!\r
879    *\r
880    * @param e DOCUMENT ME!\r
881    */\r
882   public void remove2LeftMenuItem_actionPerformed(ActionEvent e)\r
883   {\r
884     ColumnSelection colSel = viewport.getColumnSelection();\r
885 \r
886     if (colSel.size() > 0)\r
887     {\r
888       addHistoryItem(new HistoryItem("Remove Left", viewport.alignment,\r
889                                      HistoryItem.HIDE));\r
890 \r
891       int min = colSel.getMin();\r
892       viewport.getAlignment().trimLeft(min);\r
893       colSel.compensateForEdit(0, min);\r
894 \r
895       if (viewport.getSelectionGroup() != null)\r
896       {\r
897         viewport.getSelectionGroup().adjustForRemoveLeft(min);\r
898       }\r
899 \r
900       Vector groups = viewport.alignment.getGroups();\r
901 \r
902       for (int i = 0; i < groups.size(); i++)\r
903       {\r
904         SequenceGroup sg = (SequenceGroup) groups.get(i);\r
905 \r
906         if (!sg.adjustForRemoveLeft(min))\r
907         {\r
908           viewport.alignment.deleteGroup(sg);\r
909         }\r
910       }\r
911 \r
912       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
913     }\r
914   }\r
915 \r
916   /**\r
917    * DOCUMENT ME!\r
918    *\r
919    * @param e DOCUMENT ME!\r
920    */\r
921   public void remove2RightMenuItem_actionPerformed(ActionEvent e)\r
922   {\r
923     ColumnSelection colSel = viewport.getColumnSelection();\r
924 \r
925     if (colSel.size() > 0)\r
926     {\r
927       addHistoryItem(new HistoryItem("Remove Right", viewport.alignment,\r
928                                      HistoryItem.HIDE));\r
929 \r
930       int max = colSel.getMax();\r
931       viewport.getAlignment().trimRight(max);\r
932 \r
933       if (viewport.getSelectionGroup() != null)\r
934       {\r
935         viewport.getSelectionGroup().adjustForRemoveRight(max);\r
936       }\r
937 \r
938       Vector groups = viewport.alignment.getGroups();\r
939 \r
940       for (int i = 0; i < groups.size(); i++)\r
941       {\r
942         SequenceGroup sg = (SequenceGroup) groups.get(i);\r
943 \r
944         if (!sg.adjustForRemoveRight(max))\r
945         {\r
946           viewport.alignment.deleteGroup(sg);\r
947         }\r
948       }\r
949 \r
950       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
951     }\r
952   }\r
953 \r
954   /**\r
955    * DOCUMENT ME!\r
956    *\r
957    * @param e DOCUMENT ME!\r
958    */\r
959   public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)\r
960   {\r
961     addHistoryItem(new HistoryItem("Remove Gapped Columns",\r
962                                    viewport.alignment, HistoryItem.HIDE));\r
963 \r
964     //This is to maintain viewport position on first residue\r
965     //of first sequence\r
966     SequenceI seq = viewport.alignment.getSequenceAt(0);\r
967     int startRes = seq.findPosition(viewport.startRes);\r
968 \r
969     viewport.getAlignment().removeGaps();\r
970 \r
971     viewport.setStartRes(seq.findIndex(startRes)-1);\r
972 \r
973    viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
974   }\r
975 \r
976   /**\r
977    * DOCUMENT ME!\r
978    *\r
979    * @param e DOCUMENT ME!\r
980    */\r
981   public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)\r
982   {\r
983     addHistoryItem(new HistoryItem("Remove Gaps", viewport.alignment,\r
984                                    HistoryItem.HIDE));\r
985 \r
986     //This is to maintain viewport position on first residue\r
987     //of first sequence\r
988     SequenceI seq = viewport.alignment.getSequenceAt(0);\r
989     int startRes = seq.findPosition(viewport.startRes);\r
990 \r
991 \r
992     SequenceI current;\r
993     int jSize;\r
994 \r
995     Vector seqs = null;\r
996 \r
997     int start = 0;\r
998     int end = viewport.alignment.getWidth();\r
999 \r
1000     if (viewport.getSelectionGroup() != null\r
1001         && viewport.getSelectionGroup().sequences != null\r
1002         && viewport.getSelectionGroup().sequences.size() > 0)\r
1003     {\r
1004       seqs = viewport.getSelectionGroup().sequences;\r
1005       start = viewport.getSelectionGroup().getStartRes();\r
1006       end = viewport.getSelectionGroup().getEndRes()+1;\r
1007     }\r
1008     else\r
1009     {\r
1010       seqs = viewport.alignment.getSequences();\r
1011     }\r
1012 \r
1013     for (int i = 0; i < seqs.size(); i++)\r
1014     {\r
1015       current = (SequenceI) seqs.elementAt(i);\r
1016       jSize = current.getLength();\r
1017 \r
1018       // Removing a range is much quicker than removing gaps\r
1019       // one by one for long sequences\r
1020       int j = start;\r
1021       int rangeStart=-1, rangeEnd=-1;\r
1022 \r
1023       do\r
1024       {\r
1025         if (jalview.util.Comparison.isGap(current.getCharAt(j)))\r
1026         {\r
1027           if(rangeStart==-1)\r
1028            {\r
1029              rangeStart = j;\r
1030              rangeEnd = j+1;\r
1031            }\r
1032            else\r
1033            {\r
1034              rangeEnd++;\r
1035            }\r
1036            j++;\r
1037         }\r
1038         else\r
1039         {\r
1040           if(rangeStart>-1)\r
1041           {\r
1042             current.deleteChars(rangeStart, rangeEnd);\r
1043             j-=rangeEnd-rangeStart;\r
1044             jSize-=rangeEnd-rangeStart;\r
1045             rangeStart = -1;\r
1046             rangeEnd = -1;\r
1047           }\r
1048           else\r
1049             j++;\r
1050         }\r
1051       }\r
1052       while (j < end && j < jSize);\r
1053       if(rangeStart>-1)\r
1054       {\r
1055        current.deleteChars(rangeStart, rangeEnd);\r
1056       }\r
1057     }\r
1058 \r
1059     viewport.setStartRes(seq.findIndex(startRes)-1);\r
1060 \r
1061     viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());\r
1062   }\r
1063 \r
1064  public void alignmentChanged()\r
1065  {\r
1066    if(viewport.vconsensus!=null)\r
1067    {\r
1068      viewport.updateConsensus();\r
1069      viewport.updateConservation();\r
1070    }\r
1071    resetAllColourSchemes();\r
1072    if(alignPanel.overviewPanel!=null)\r
1073      alignPanel.overviewPanel.updateOverviewImage();\r
1074 \r
1075    alignPanel.repaint();\r
1076  }\r
1077 \r
1078   void resetAllColourSchemes()\r
1079   {\r
1080     ColourSchemeI cs = viewport.globalColourScheme;\r
1081     if(cs!=null)\r
1082     {\r
1083       if (cs instanceof ClustalxColourScheme)\r
1084       {\r
1085         ( (ClustalxColourScheme) viewport.getGlobalColourScheme()).\r
1086             resetClustalX(viewport.alignment.getSequences(),\r
1087                           viewport.alignment.getWidth());\r
1088       }\r
1089 \r
1090       cs.setConsensus(viewport.vconsensus);\r
1091       if (cs.conservationApplied())\r
1092       {\r
1093         Alignment al = (Alignment) viewport.alignment;\r
1094         Conservation c = new Conservation("All",\r
1095                                           ResidueProperties.propHash, 3,\r
1096                                           al.getSequences(), 0,\r
1097                                           al.getWidth() - 1);\r
1098         c.calculate();\r
1099         c.verdict(false, viewport.ConsPercGaps);\r
1100 \r
1101         cs.setConservation(c);\r
1102       }\r
1103     }\r
1104 \r
1105     int s, sSize = viewport.alignment.getGroups().size();\r
1106     for(s=0; s<sSize; s++)\r
1107     {\r
1108       SequenceGroup sg = (SequenceGroup)viewport.alignment.getGroups().elementAt(s);\r
1109       if(sg.cs!=null && sg.cs instanceof ClustalxColourScheme)\r
1110       {\r
1111         ((ClustalxColourScheme)sg.cs).resetClustalX(sg.sequences, sg.getWidth());\r
1112       }\r
1113       sg.recalcConservation();\r
1114     }\r
1115   }\r
1116 \r
1117   /**\r
1118    * DOCUMENT ME!\r
1119    *\r
1120    * @param e DOCUMENT ME!\r
1121    */\r
1122   public void padGapsMenuitem_actionPerformed(ActionEvent e)\r
1123   {\r
1124     addHistoryItem(new HistoryItem("Pad Gaps", viewport.alignment,\r
1125                                    HistoryItem.HIDE));\r
1126 \r
1127     SequenceI current;\r
1128     int Width = viewport.getAlignment().getWidth();\r
1129 \r
1130     for (int i = 0; i < viewport.getAlignment().getSequences().size();\r
1131          i++)\r
1132     {\r
1133       current = viewport.getAlignment().getSequenceAt(i);\r
1134 \r
1135       if (current.getLength() < Width)\r
1136       {\r
1137         current.insertCharAt(Width - 1, viewport.getGapCharacter());\r
1138       }\r
1139     }\r
1140 \r
1141     alignmentChanged();\r
1142   }\r
1143 \r
1144   /**\r
1145    * DOCUMENT ME!\r
1146    *\r
1147    * @param e DOCUMENT ME!\r
1148    */\r
1149   public void findMenuItem_actionPerformed(ActionEvent e)\r
1150   {\r
1151     JInternalFrame frame = new JInternalFrame();\r
1152     Finder finder = new Finder(viewport, alignPanel, frame);\r
1153     frame.setContentPane(finder);\r
1154     Desktop.addInternalFrame(frame, "Find", 340, 110);\r
1155     frame.setLayer(JLayeredPane.PALETTE_LAYER);\r
1156   }\r
1157 \r
1158   /**\r
1159    * DOCUMENT ME!\r
1160    *\r
1161    * @param e DOCUMENT ME!\r
1162    */\r
1163   public void font_actionPerformed(ActionEvent e)\r
1164   {\r
1165     FontChooser fc = new FontChooser(alignPanel);\r
1166   }\r
1167 \r
1168   /**\r
1169    * DOCUMENT ME!\r
1170    *\r
1171    * @param e DOCUMENT ME!\r
1172    */\r
1173   protected void fullSeqId_actionPerformed(ActionEvent e)\r
1174   {\r
1175     viewport.setShowFullId(fullSeqId.isSelected());\r
1176 \r
1177     alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel.calculateIdWidth());\r
1178     alignPanel.repaint();\r
1179   }\r
1180 \r
1181   /**\r
1182    * DOCUMENT ME!\r
1183    *\r
1184    * @param e DOCUMENT ME!\r
1185    */\r
1186   protected void colourTextMenuItem_actionPerformed(ActionEvent e)\r
1187   {\r
1188     viewport.setColourText(colourTextMenuItem.isSelected());\r
1189     alignPanel.repaint();\r
1190   }\r
1191 \r
1192   /**\r
1193    * DOCUMENT ME!\r
1194    *\r
1195    * @param e DOCUMENT ME!\r
1196    */\r
1197   protected void wrapMenuItem_actionPerformed(ActionEvent e)\r
1198   {\r
1199     viewport.setWrapAlignment(wrapMenuItem.isSelected());\r
1200     alignPanel.setWrapAlignment(wrapMenuItem.isSelected());\r
1201     scaleAbove.setVisible(wrapMenuItem.isSelected());\r
1202     scaleLeft.setVisible(wrapMenuItem.isSelected());\r
1203     scaleRight.setVisible(wrapMenuItem.isSelected());\r
1204     alignPanel.repaint();\r
1205   }\r
1206 \r
1207   /**\r
1208    * DOCUMENT ME!\r
1209    *\r
1210    * @param e DOCUMENT ME!\r
1211    */\r
1212   protected void scaleAbove_actionPerformed(ActionEvent e)\r
1213   {\r
1214     viewport.setScaleAboveWrapped(scaleAbove.isSelected());\r
1215     alignPanel.repaint();\r
1216   }\r
1217 \r
1218   /**\r
1219    * DOCUMENT ME!\r
1220    *\r
1221    * @param e DOCUMENT ME!\r
1222    */\r
1223   protected void scaleLeft_actionPerformed(ActionEvent e)\r
1224   {\r
1225     viewport.setScaleLeftWrapped(scaleLeft.isSelected());\r
1226     alignPanel.repaint();\r
1227   }\r
1228 \r
1229   /**\r
1230    * DOCUMENT ME!\r
1231    *\r
1232    * @param e DOCUMENT ME!\r
1233    */\r
1234   protected void scaleRight_actionPerformed(ActionEvent e)\r
1235   {\r
1236     viewport.setScaleRightWrapped(scaleRight.isSelected());\r
1237     alignPanel.repaint();\r
1238   }\r
1239 \r
1240   /**\r
1241    * DOCUMENT ME!\r
1242    *\r
1243    * @param e DOCUMENT ME!\r
1244    */\r
1245   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)\r
1246   {\r
1247     viewport.setShowBoxes(viewBoxesMenuItem.isSelected());\r
1248     alignPanel.repaint();\r
1249   }\r
1250 \r
1251   /**\r
1252    * DOCUMENT ME!\r
1253    *\r
1254    * @param e DOCUMENT ME!\r
1255    */\r
1256   public void viewTextMenuItem_actionPerformed(ActionEvent e)\r
1257   {\r
1258     viewport.setShowText(viewTextMenuItem.isSelected());\r
1259     alignPanel.repaint();\r
1260   }\r
1261 \r
1262   /**\r
1263    * DOCUMENT ME!\r
1264    *\r
1265    * @param e DOCUMENT ME!\r
1266    */\r
1267   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)\r
1268   {\r
1269     viewport.setRenderGaps(renderGapsMenuItem.isSelected());\r
1270     alignPanel.repaint();\r
1271   }\r
1272 \r
1273   /**\r
1274    * DOCUMENT ME!\r
1275    *\r
1276    * @param evt DOCUMENT ME!\r
1277    */\r
1278   public void sequenceFeatures_actionPerformed(ActionEvent evt)\r
1279   {\r
1280     viewport.showSequenceFeatures(sequenceFeatures.isSelected());\r
1281 \r
1282     if (viewport.showSequenceFeatures &&\r
1283         ! ( (Alignment) viewport.alignment).featuresAdded)\r
1284     {\r
1285       SequenceFeatureFetcher sft = new SequenceFeatureFetcher(viewport.\r
1286           alignment,\r
1287           alignPanel);\r
1288       ( (Alignment) viewport.alignment).featuresAdded = true;\r
1289     }\r
1290 \r
1291     alignPanel.repaint();\r
1292   }\r
1293 \r
1294   /**\r
1295    * DOCUMENT ME!\r
1296    *\r
1297    * @param e DOCUMENT ME!\r
1298    */\r
1299   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)\r
1300   {\r
1301     if (annotationPanelMenuItem.isSelected() &&\r
1302         viewport.getWrapAlignment())\r
1303     {\r
1304       annotationPanelMenuItem.setSelected(false);\r
1305 \r
1306       return;\r
1307     }\r
1308 \r
1309     viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());\r
1310     alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());\r
1311   }\r
1312 \r
1313   /**\r
1314    * DOCUMENT ME!\r
1315    *\r
1316    * @param e DOCUMENT ME!\r
1317    */\r
1318   public void overviewMenuItem_actionPerformed(ActionEvent e)\r
1319   {\r
1320     if (alignPanel.overviewPanel != null)\r
1321     {\r
1322       return;\r
1323     }\r
1324 \r
1325     JInternalFrame frame = new JInternalFrame();\r
1326     OverviewPanel overview = new OverviewPanel(alignPanel);\r
1327     frame.setContentPane(overview);\r
1328     Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),\r
1329                              frame.getWidth(), frame.getHeight());\r
1330     frame.pack();\r
1331     frame.setLayer(JLayeredPane.PALETTE_LAYER);\r
1332     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()\r
1333     {\r
1334       public void internalFrameClosed(\r
1335           javax.swing.event.InternalFrameEvent evt)\r
1336       {\r
1337         alignPanel.setOverviewPanel(null);\r
1338       }\r
1339       ;\r
1340     });\r
1341 \r
1342     alignPanel.setOverviewPanel(overview);\r
1343   }\r
1344 \r
1345   /**\r
1346    * DOCUMENT ME!\r
1347    *\r
1348    * @param e DOCUMENT ME!\r
1349    */\r
1350   protected void noColourmenuItem_actionPerformed(ActionEvent e)\r
1351   {\r
1352     changeColour(null);\r
1353   }\r
1354 \r
1355   /**\r
1356    * DOCUMENT ME!\r
1357    *\r
1358    * @param e DOCUMENT ME!\r
1359    */\r
1360   public void clustalColour_actionPerformed(ActionEvent e)\r
1361   {\r
1362     changeColour(new ClustalxColourScheme(\r
1363         viewport.alignment.getSequences(), viewport.alignment.getWidth()));\r
1364   }\r
1365 \r
1366   /**\r
1367    * DOCUMENT ME!\r
1368    *\r
1369    * @param e DOCUMENT ME!\r
1370    */\r
1371   public void zappoColour_actionPerformed(ActionEvent e)\r
1372   {\r
1373     changeColour(new ZappoColourScheme());\r
1374   }\r
1375 \r
1376   /**\r
1377    * DOCUMENT ME!\r
1378    *\r
1379    * @param e DOCUMENT ME!\r
1380    */\r
1381   public void taylorColour_actionPerformed(ActionEvent e)\r
1382   {\r
1383     changeColour(new TaylorColourScheme());\r
1384   }\r
1385 \r
1386   /**\r
1387    * DOCUMENT ME!\r
1388    *\r
1389    * @param e DOCUMENT ME!\r
1390    */\r
1391   public void hydrophobicityColour_actionPerformed(ActionEvent e)\r
1392   {\r
1393     changeColour(new HydrophobicColourScheme());\r
1394   }\r
1395 \r
1396   /**\r
1397    * DOCUMENT ME!\r
1398    *\r
1399    * @param e DOCUMENT ME!\r
1400    */\r
1401   public void helixColour_actionPerformed(ActionEvent e)\r
1402   {\r
1403     changeColour(new HelixColourScheme());\r
1404   }\r
1405 \r
1406   /**\r
1407    * DOCUMENT ME!\r
1408    *\r
1409    * @param e DOCUMENT ME!\r
1410    */\r
1411   public void strandColour_actionPerformed(ActionEvent e)\r
1412   {\r
1413     changeColour(new StrandColourScheme());\r
1414   }\r
1415 \r
1416   /**\r
1417    * DOCUMENT ME!\r
1418    *\r
1419    * @param e DOCUMENT ME!\r
1420    */\r
1421   public void turnColour_actionPerformed(ActionEvent e)\r
1422   {\r
1423     changeColour(new TurnColourScheme());\r
1424   }\r
1425 \r
1426   /**\r
1427    * DOCUMENT ME!\r
1428    *\r
1429    * @param e DOCUMENT ME!\r
1430    */\r
1431   public void buriedColour_actionPerformed(ActionEvent e)\r
1432   {\r
1433     changeColour(new BuriedColourScheme());\r
1434   }\r
1435 \r
1436   /**\r
1437    * DOCUMENT ME!\r
1438    *\r
1439    * @param e DOCUMENT ME!\r
1440    */\r
1441   public void nucleotideColour_actionPerformed(ActionEvent e)\r
1442   {\r
1443     changeColour(new NucleotideColourScheme());\r
1444   }\r
1445 \r
1446   /**\r
1447    * DOCUMENT ME!\r
1448    *\r
1449    * @param e DOCUMENT ME!\r
1450    */\r
1451   protected void applyToAllGroups_actionPerformed(ActionEvent e)\r
1452   {\r
1453     viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());\r
1454   }\r
1455 \r
1456   /**\r
1457    * DOCUMENT ME!\r
1458    *\r
1459    * @param cs DOCUMENT ME!\r
1460    */\r
1461   void changeColour(ColourSchemeI cs)\r
1462   {\r
1463     int threshold = 0;\r
1464 \r
1465     if(cs!=null)\r
1466     {\r
1467       if (viewport.getAbovePIDThreshold())\r
1468       {\r
1469         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,\r
1470                                                    "Background");\r
1471 \r
1472         cs.setThreshold(threshold,\r
1473                         viewport.getIgnoreGapsConsensus());\r
1474 \r
1475         viewport.setGlobalColourScheme(cs);\r
1476       }\r
1477       else\r
1478       {\r
1479         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
1480       }\r
1481 \r
1482       if (viewport.getConservationSelected())\r
1483       {\r
1484 \r
1485         Alignment al = (Alignment) viewport.alignment;\r
1486         Conservation c = new Conservation("All",\r
1487                                           ResidueProperties.propHash, 3,\r
1488                                           al.getSequences(), 0,\r
1489                                           al.getWidth() - 1);\r
1490 \r
1491         c.calculate();\r
1492         c.verdict(false, viewport.ConsPercGaps);\r
1493 \r
1494         cs.setConservation(c);\r
1495 \r
1496         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,\r
1497             "Background"));\r
1498       }\r
1499       else\r
1500       {\r
1501         cs.setConservation(null);\r
1502       }\r
1503 \r
1504       cs.setConsensus(viewport.vconsensus);\r
1505     }\r
1506 \r
1507     viewport.setGlobalColourScheme(cs);\r
1508 \r
1509     if (viewport.getColourAppliesToAllGroups())\r
1510     {\r
1511       Vector groups = viewport.alignment.getGroups();\r
1512 \r
1513       for (int i = 0; i < groups.size(); i++)\r
1514       {\r
1515         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
1516 \r
1517         if (cs == null)\r
1518         {\r
1519           sg.cs = null;\r
1520           continue;\r
1521         }\r
1522 \r
1523         if (cs instanceof ClustalxColourScheme)\r
1524         {\r
1525           sg.cs = new ClustalxColourScheme(sg.sequences, sg.getWidth());\r
1526         }\r
1527         else if (cs instanceof UserColourScheme)\r
1528         {\r
1529           sg.cs = new UserColourScheme( ( (UserColourScheme) cs).getColours());\r
1530         }\r
1531         else\r
1532         {\r
1533           try\r
1534           {\r
1535             sg.cs = (ColourSchemeI) cs.getClass().newInstance();\r
1536           }\r
1537           catch (Exception ex)\r
1538           {\r
1539           }\r
1540         }\r
1541 \r
1542         if (viewport.getAbovePIDThreshold()\r
1543             || cs instanceof PIDColourScheme\r
1544             || cs instanceof Blosum62ColourScheme)\r
1545         {\r
1546          sg.cs.setThreshold(threshold,\r
1547                 viewport.getIgnoreGapsConsensus());\r
1548 \r
1549           sg.cs.setConsensus(AAFrequency.calculate(sg.sequences, 0,\r
1550               sg.getWidth()));\r
1551         }\r
1552         else\r
1553           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
1554 \r
1555 \r
1556         if (viewport.getConservationSelected())\r
1557         {\r
1558           Conservation c = new Conservation("Group",\r
1559                                             ResidueProperties.propHash, 3,\r
1560                                             sg.sequences, 0,\r
1561                                             viewport.alignment.getWidth() - 1);\r
1562           c.calculate();\r
1563           c.verdict(false, viewport.ConsPercGaps);\r
1564           sg.cs.setConservation(c);\r
1565         }\r
1566         else\r
1567           sg.cs.setConservation(null);\r
1568       }\r
1569     }\r
1570 \r
1571     if (alignPanel.getOverviewPanel() != null)\r
1572     {\r
1573       alignPanel.getOverviewPanel().updateOverviewImage();\r
1574     }\r
1575 \r
1576     alignPanel.repaint();\r
1577   }\r
1578 \r
1579   /**\r
1580    * DOCUMENT ME!\r
1581    *\r
1582    * @param e DOCUMENT ME!\r
1583    */\r
1584   protected void modifyPID_actionPerformed(ActionEvent e)\r
1585   {\r
1586     if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme!=null)\r
1587     {\r
1588       SliderPanel.setPIDSliderSource(alignPanel,\r
1589                                      viewport.getGlobalColourScheme(),\r
1590                                      "Background");\r
1591       SliderPanel.showPIDSlider();\r
1592     }\r
1593   }\r
1594 \r
1595   /**\r
1596    * DOCUMENT ME!\r
1597    *\r
1598    * @param e DOCUMENT ME!\r
1599    */\r
1600   protected void modifyConservation_actionPerformed(ActionEvent e)\r
1601   {\r
1602     if (viewport.getConservationSelected() && viewport.globalColourScheme!=null)\r
1603     {\r
1604       SliderPanel.setConservationSlider(alignPanel,\r
1605                                         viewport.globalColourScheme,\r
1606                                         "Background");\r
1607       SliderPanel.showConservationSlider();\r
1608     }\r
1609   }\r
1610 \r
1611   /**\r
1612    * DOCUMENT ME!\r
1613    *\r
1614    * @param e DOCUMENT ME!\r
1615    */\r
1616   protected void conservationMenuItem_actionPerformed(ActionEvent e)\r
1617   {\r
1618     viewport.setConservationSelected(conservationMenuItem.isSelected());\r
1619 \r
1620     viewport.setAbovePIDThreshold(false);\r
1621     abovePIDThreshold.setSelected(false);\r
1622 \r
1623     changeColour(viewport.getGlobalColourScheme());\r
1624 \r
1625     modifyConservation_actionPerformed(null);\r
1626   }\r
1627 \r
1628   /**\r
1629    * DOCUMENT ME!\r
1630    *\r
1631    * @param e DOCUMENT ME!\r
1632    */\r
1633   public void abovePIDThreshold_actionPerformed(ActionEvent e)\r
1634   {\r
1635     viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());\r
1636 \r
1637     conservationMenuItem.setSelected(false);\r
1638     viewport.setConservationSelected(false);\r
1639 \r
1640     ColourSchemeI cs = viewport.getGlobalColourScheme();\r
1641 \r
1642     changeColour(viewport.getGlobalColourScheme());\r
1643 \r
1644     modifyPID_actionPerformed(null);\r
1645   }\r
1646 \r
1647   /**\r
1648    * DOCUMENT ME!\r
1649    *\r
1650    * @param e DOCUMENT ME!\r
1651    */\r
1652   public void userDefinedColour_actionPerformed(ActionEvent e)\r
1653   {\r
1654     if (e.getActionCommand().equals("User Defined..."))\r
1655     {\r
1656       new UserDefinedColours(alignPanel, null);\r
1657     }\r
1658     else\r
1659     {\r
1660       UserColourScheme udc = (UserColourScheme) UserDefinedColours.\r
1661           getUserColourSchemes().get(e.getActionCommand());\r
1662 \r
1663       changeColour(udc);\r
1664     }\r
1665   }\r
1666 \r
1667   public void updateUserColourMenu()\r
1668   {\r
1669 \r
1670     Component[] menuItems = colourMenu.getMenuComponents();\r
1671     int i, iSize = menuItems.length;\r
1672     for (i = 0; i < iSize; i++)\r
1673     {\r
1674       if (menuItems[i].getName() != null &&\r
1675           menuItems[i].getName().equals("USER_DEFINED"))\r
1676       {\r
1677         colourMenu.remove(menuItems[i]);\r
1678         iSize--;\r
1679       }\r
1680     }\r
1681     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)\r
1682     {\r
1683       java.util.Enumeration userColours = jalview.gui.UserDefinedColours.\r
1684           getUserColourSchemes().keys();\r
1685 \r
1686       while (userColours.hasMoreElements())\r
1687       {\r
1688         final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(userColours.\r
1689             nextElement().toString());\r
1690         radioItem.setName("USER_DEFINED");\r
1691         radioItem.addMouseListener(new MouseAdapter()\r
1692             {\r
1693               public void mousePressed(MouseEvent evt)\r
1694               {\r
1695                 if(evt.isControlDown() || SwingUtilities.isRightMouseButton(evt))\r
1696                 {\r
1697                   radioItem.removeActionListener(radioItem.getActionListeners()[0]);\r
1698 \r
1699                   int option = JOptionPane.showInternalConfirmDialog(jalview.gui.Desktop.desktop,\r
1700                       "Remove from default list?",\r
1701                       "Remove user defined colour",\r
1702                       JOptionPane.YES_NO_OPTION);\r
1703                   if(option == JOptionPane.YES_OPTION)\r
1704                   {\r
1705                     jalview.gui.UserDefinedColours.removeColourFromDefaults(radioItem.getText());\r
1706                     colourMenu.remove(radioItem);\r
1707                   }\r
1708                   else\r
1709                     radioItem.addActionListener(new ActionListener()\r
1710                     {\r
1711                       public void actionPerformed(ActionEvent evt)\r
1712                       {\r
1713                         userDefinedColour_actionPerformed(evt);\r
1714                       }\r
1715                     });\r
1716                 }\r
1717               }\r
1718             });\r
1719         radioItem.addActionListener(new ActionListener()\r
1720         {\r
1721           public void actionPerformed(ActionEvent evt)\r
1722           {\r
1723             userDefinedColour_actionPerformed(evt);\r
1724           }\r
1725         });\r
1726 \r
1727         colourMenu.insert(radioItem, 15);\r
1728         colours.add(radioItem);\r
1729       }\r
1730     }\r
1731   }\r
1732 \r
1733   /**\r
1734    * DOCUMENT ME!\r
1735    *\r
1736    * @param e DOCUMENT ME!\r
1737    */\r
1738   public void PIDColour_actionPerformed(ActionEvent e)\r
1739   {\r
1740     changeColour(new PIDColourScheme());\r
1741   }\r
1742 \r
1743   /**\r
1744    * DOCUMENT ME!\r
1745    *\r
1746    * @param e DOCUMENT ME!\r
1747    */\r
1748   public void BLOSUM62Colour_actionPerformed(ActionEvent e)\r
1749   {\r
1750     changeColour(new Blosum62ColourScheme());\r
1751   }\r
1752 \r
1753   /**\r
1754    * DOCUMENT ME!\r
1755    *\r
1756    * @param e DOCUMENT ME!\r
1757    */\r
1758   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)\r
1759   {\r
1760     addHistoryItem(new HistoryItem("Pairwise Sort", viewport.alignment,\r
1761                                    HistoryItem.SORT));\r
1762     AlignmentSorter.sortByPID(viewport.getAlignment(),\r
1763                               viewport.getAlignment().getSequenceAt(0));\r
1764     alignPanel.repaint();\r
1765   }\r
1766 \r
1767   /**\r
1768    * DOCUMENT ME!\r
1769    *\r
1770    * @param e DOCUMENT ME!\r
1771    */\r
1772   public void sortIDMenuItem_actionPerformed(ActionEvent e)\r
1773   {\r
1774     addHistoryItem(new HistoryItem("ID Sort", viewport.alignment,\r
1775                                    HistoryItem.SORT));\r
1776     AlignmentSorter.sortByID(viewport.getAlignment());\r
1777     alignPanel.repaint();\r
1778   }\r
1779 \r
1780   /**\r
1781    * DOCUMENT ME!\r
1782    *\r
1783    * @param e DOCUMENT ME!\r
1784    */\r
1785   public void sortGroupMenuItem_actionPerformed(ActionEvent e)\r
1786   {\r
1787     addHistoryItem(new HistoryItem("Group Sort", viewport.alignment,\r
1788                                    HistoryItem.SORT));\r
1789 \r
1790     AlignmentSorter.sortByGroup(viewport.getAlignment());\r
1791     alignPanel.repaint();\r
1792   }\r
1793 \r
1794   /**\r
1795    * DOCUMENT ME!\r
1796    *\r
1797    * @param e DOCUMENT ME!\r
1798    */\r
1799   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)\r
1800   {\r
1801     RedundancyPanel sp = new RedundancyPanel(alignPanel, this);\r
1802     JInternalFrame frame = new JInternalFrame();\r
1803     frame.setContentPane(sp);\r
1804     Desktop.addInternalFrame(frame, "Redundancy threshold selection", 400,\r
1805                              100, false);\r
1806   }\r
1807 \r
1808   /**\r
1809    * DOCUMENT ME!\r
1810    *\r
1811    * @param e DOCUMENT ME!\r
1812    */\r
1813   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)\r
1814   {\r
1815     if ( (viewport.getSelectionGroup() == null) ||\r
1816         (viewport.getSelectionGroup().getSize() < 2))\r
1817     {\r
1818       JOptionPane.showInternalMessageDialog(this,\r
1819                                             "You must select at least 2 sequences.",\r
1820                                             "Invalid Selection",\r
1821                                             JOptionPane.WARNING_MESSAGE);\r
1822     }\r
1823     else\r
1824     {\r
1825       JInternalFrame frame = new JInternalFrame();\r
1826       frame.setContentPane(new PairwiseAlignPanel(viewport));\r
1827       Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);\r
1828     }\r
1829   }\r
1830 \r
1831   /**\r
1832    * DOCUMENT ME!\r
1833    *\r
1834    * @param e DOCUMENT ME!\r
1835    */\r
1836   public void PCAMenuItem_actionPerformed(ActionEvent e)\r
1837   {\r
1838     if ( ( (viewport.getSelectionGroup() != null) &&\r
1839           (viewport.getSelectionGroup().getSize() < 4) &&\r
1840           (viewport.getSelectionGroup().getSize() > 0)) ||\r
1841         (viewport.getAlignment().getHeight() < 4))\r
1842     {\r
1843       JOptionPane.showInternalMessageDialog(this,\r
1844                                             "Principal component analysis must take\n" +\r
1845                                             "at least 4 input sequences.",\r
1846                                             "Sequence selection insufficient",\r
1847                                             JOptionPane.WARNING_MESSAGE);\r
1848 \r
1849       return;\r
1850     }\r
1851 \r
1852     try\r
1853     {\r
1854       PCAPanel pcaPanel = new PCAPanel(viewport, null);\r
1855       JInternalFrame frame = new JInternalFrame();\r
1856       frame.setContentPane(pcaPanel);\r
1857       Desktop.addInternalFrame(frame, "Principal component analysis",\r
1858                                400, 400);\r
1859     }\r
1860     catch (java.lang.OutOfMemoryError ex)\r
1861     {\r
1862       JOptionPane.showInternalMessageDialog(this,\r
1863                                             "Too many sequences selected\nfor Principal Component Analysis!!",\r
1864                                             "Out of memory",\r
1865                                             JOptionPane.WARNING_MESSAGE);\r
1866     }\r
1867   }\r
1868 \r
1869   /**\r
1870    * DOCUMENT ME!\r
1871    *\r
1872    * @param e DOCUMENT ME!\r
1873    */\r
1874   public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)\r
1875   {\r
1876     NewTreePanel("AV", "PID", "Average distance tree using PID");\r
1877   }\r
1878 \r
1879   /**\r
1880    * DOCUMENT ME!\r
1881    *\r
1882    * @param e DOCUMENT ME!\r
1883    */\r
1884   public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)\r
1885   {\r
1886     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");\r
1887   }\r
1888 \r
1889   /**\r
1890    * DOCUMENT ME!\r
1891    *\r
1892    * @param e DOCUMENT ME!\r
1893    */\r
1894   protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
1895   {\r
1896     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");\r
1897   }\r
1898 \r
1899   /**\r
1900    * DOCUMENT ME!\r
1901    *\r
1902    * @param e DOCUMENT ME!\r
1903    */\r
1904   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
1905   {\r
1906     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");\r
1907   }\r
1908 \r
1909   /**\r
1910    * DOCUMENT ME!\r
1911    *\r
1912    * @param type DOCUMENT ME!\r
1913    * @param pwType DOCUMENT ME!\r
1914    * @param title DOCUMENT ME!\r
1915    */\r
1916   void NewTreePanel(String type, String pwType, String title)\r
1917   {\r
1918     final TreePanel tp;\r
1919 \r
1920     if ( (viewport.getSelectionGroup() != null) &&\r
1921         (viewport.getSelectionGroup().getSize() > 3))\r
1922     {\r
1923       int s = 0;\r
1924       SequenceGroup sg = viewport.getSelectionGroup();\r
1925 \r
1926       /* Decide if the selection is a column region */\r
1927       while (s < sg.sequences.size())\r
1928       {\r
1929         if ( ( (SequenceI) sg.sequences.elementAt(s++)).getLength() <\r
1930             sg.getEndRes())\r
1931         {\r
1932           JOptionPane.showMessageDialog(Desktop.desktop,\r
1933                                         "The selected region to create a tree may\nonly contain residues or gaps.\n" +\r
1934                                         "Try using the Pad function in the edit menu,\n" +\r
1935                                         "or one of the multiple sequence alignment web services.",\r
1936                                         "Sequences in selection are not aligned",\r
1937                                         JOptionPane.WARNING_MESSAGE);\r
1938 \r
1939           return;\r
1940         }\r
1941       }\r
1942 \r
1943       title = title + " on region";\r
1944       tp = new TreePanel(viewport,\r
1945                          viewport.getSelectionGroup().sequences, type, pwType,\r
1946                          sg.getStartRes(), sg.getEndRes());\r
1947     }\r
1948     else\r
1949     {\r
1950       //are the sequences aligned?\r
1951       if (!viewport.alignment.isAligned())\r
1952       {\r
1953         JOptionPane.showMessageDialog(Desktop.desktop,\r
1954                                       "The sequences must be aligned before creating a tree.\n" +\r
1955                                       "Try using the Pad function in the edit menu,\n" +\r
1956                                       "or one of the multiple sequence alignment web services.",\r
1957                                       "Sequences not aligned",\r
1958                                       JOptionPane.WARNING_MESSAGE);\r
1959 \r
1960         return;\r
1961       }\r
1962 \r
1963       tp = new TreePanel(viewport,\r
1964                          viewport.getAlignment().getSequences(), type, pwType,\r
1965                          0,\r
1966                          viewport.alignment.getWidth());\r
1967     }\r
1968 \r
1969     addTreeMenuItem(tp, title);\r
1970     viewport.setCurrentTree(tp.getTree());\r
1971 \r
1972     Desktop.addInternalFrame(tp, title + " from " + this.title, 600, 500);\r
1973   }\r
1974 \r
1975   /**\r
1976    * DOCUMENT ME!\r
1977    *\r
1978    * @param title DOCUMENT ME!\r
1979    * @param order DOCUMENT ME!\r
1980    */\r
1981   public void addSortByOrderMenuItem(String title, final AlignmentOrder order)\r
1982   {\r
1983     final JMenuItem item = new JMenuItem("by " + title);\r
1984     sort.add(item);\r
1985     item.addActionListener(new java.awt.event.ActionListener()\r
1986     {\r
1987       public void actionPerformed(ActionEvent e)\r
1988       {\r
1989         addHistoryItem(new HistoryItem("Sort", viewport.alignment,\r
1990                                        HistoryItem.SORT));\r
1991 \r
1992         // TODO: JBPNote - have to map order entries to curent SequenceI pointers\r
1993         AlignmentSorter.sortBy(viewport.getAlignment(), order);\r
1994         alignPanel.repaint();\r
1995       }\r
1996     });\r
1997   }\r
1998 \r
1999   /**\r
2000    * Maintain the Order by->Displayed Tree menu.\r
2001    * Creates a new menu item for a TreePanel with an appropriate\r
2002    * <code>jalview.analysis.AlignmentSorter</code> call. Listeners are added\r
2003    * to remove the menu item when the treePanel is closed, and adjust\r
2004    * the tree leaf to sequence mapping when the alignment is modified.\r
2005    * @param treePanel Displayed tree window.\r
2006    * @param title SortBy menu item title.\r
2007    */\r
2008   void addTreeMenuItem(final TreePanel treePanel, String title)\r
2009   {\r
2010     final JMenuItem item = new JMenuItem(title);\r
2011 \r
2012     treeCount++;\r
2013 \r
2014     if (treeCount == 1)\r
2015     {\r
2016       sort.add(sortByTreeMenu);\r
2017     }\r
2018 \r
2019     sortByTreeMenu.add(item);\r
2020     item.addActionListener(new java.awt.event.ActionListener()\r
2021     {\r
2022       public void actionPerformed(ActionEvent e)\r
2023       {\r
2024         addHistoryItem(new HistoryItem("Tree Sort",\r
2025                                        viewport.alignment, HistoryItem.SORT));\r
2026         AlignmentSorter.sortByTree(viewport.getAlignment(),\r
2027                                    treePanel.getTree());\r
2028         alignPanel.repaint();\r
2029       }\r
2030     });\r
2031 \r
2032     treePanel.addInternalFrameListener(new javax.swing.event.\r
2033                                        InternalFrameAdapter()\r
2034     {\r
2035       public void internalFrameClosed(\r
2036           javax.swing.event.InternalFrameEvent evt)\r
2037       {\r
2038         treeCount--;\r
2039         sortByTreeMenu.remove(item);\r
2040 \r
2041         if (treeCount == 0)\r
2042         {\r
2043           sort.remove(sortByTreeMenu);\r
2044         }\r
2045       }\r
2046       ;\r
2047     });\r
2048   }\r
2049 \r
2050   /**\r
2051    * Work out whether the whole set of sequences\r
2052    * or just the selected set will be submitted for multiple alignment.\r
2053    *\r
2054    */\r
2055   private SequenceI[] gatherSequencesForAlignment()\r
2056   {\r
2057     // Now, check we have enough sequences\r
2058     SequenceI[] msa = null;\r
2059 \r
2060     if ( (viewport.getSelectionGroup() != null) &&\r
2061         (viewport.getSelectionGroup().getSize() > 1))\r
2062     {\r
2063       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!\r
2064       SequenceGroup seqs = viewport.getSelectionGroup();\r
2065       int sz;\r
2066       msa = new SequenceI[sz = seqs.getSize()];\r
2067 \r
2068       for (int i = 0; i < sz; i++)\r
2069       {\r
2070         msa[i] = (SequenceI) seqs.getSequenceAt(i);\r
2071       }\r
2072     }\r
2073     else\r
2074     {\r
2075       Vector seqs = viewport.getAlignment().getSequences();\r
2076 \r
2077       if (seqs.size() > 1)\r
2078       {\r
2079         msa = new SequenceI[seqs.size()];\r
2080 \r
2081         for (int i = 0; i < seqs.size(); i++)\r
2082         {\r
2083           msa[i] = (SequenceI) seqs.elementAt(i);\r
2084         }\r
2085       }\r
2086     }\r
2087     return msa;\r
2088   }\r
2089 \r
2090   /**\r
2091    * Decides what is submitted to a secondary structure prediction service,\r
2092    * the currently selected sequence, or the currently selected alignment\r
2093    * (where the first sequence in the set is the one that the prediction\r
2094    * will be for).\r
2095    */\r
2096   SequenceI[] gatherSeqOrMsaForSecStrPrediction()\r
2097   {\r
2098     SequenceI seq = null;\r
2099     SequenceI[] msa = null;\r
2100 \r
2101     if ( (viewport.getSelectionGroup() != null) &&\r
2102         (viewport.getSelectionGroup().getSize() > 0))\r
2103     {\r
2104       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!\r
2105       SequenceGroup seqs = viewport.getSelectionGroup();\r
2106 \r
2107       if ( (seqs.getSize() == 1) || !viewport.alignment.isAligned())\r
2108       {\r
2109         seq = (SequenceI) seqs.getSequenceAt(0);\r
2110       }\r
2111       else\r
2112       {\r
2113         int sz;\r
2114         msa = new SequenceI[sz = seqs.getSize()];\r
2115 \r
2116         for (int i = 0; i < sz; i++)\r
2117         {\r
2118           msa[i] = (SequenceI) seqs.getSequenceAt(i);\r
2119         }\r
2120       }\r
2121     }\r
2122     else\r
2123     {\r
2124       Vector seqs = viewport.getAlignment().getSequences();\r
2125 \r
2126       if ( (seqs.size() == 1) || !viewport.alignment.isAligned())\r
2127       {\r
2128         seq = (SequenceI) seqs.elementAt(0);\r
2129       }\r
2130       else\r
2131       {\r
2132         msa = new SequenceI[seqs.size()];\r
2133 \r
2134         for (int i = 0; i < seqs.size(); i++)\r
2135         {\r
2136           msa[i] = (SequenceI) seqs.elementAt(i);\r
2137         }\r
2138       }\r
2139     }\r
2140     if (msa != null)\r
2141     {\r
2142       return msa;\r
2143     }\r
2144     else\r
2145     {\r
2146       if (seq != null)\r
2147       {\r
2148         return new SequenceI[]\r
2149             {\r
2150             seq};\r
2151       }\r
2152     }\r
2153     return null;\r
2154   }\r
2155   /**\r
2156    * DOCUMENT ME!\r
2157    *\r
2158    * @param e DOCUMENT ME!\r
2159    */\r
2160   protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)\r
2161   {\r
2162     // Pick the tree file\r
2163     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.\r
2164         getProperty(\r
2165             "LAST_DIRECTORY"));\r
2166     chooser.setFileView(new JalviewFileView());\r
2167     chooser.setDialogTitle("Select a newick-like tree file");\r
2168     chooser.setToolTipText("Load a tree file");\r
2169 \r
2170     int value = chooser.showOpenDialog(null);\r
2171 \r
2172     if (value == JalviewFileChooser.APPROVE_OPTION)\r
2173     {\r
2174       String choice = chooser.getSelectedFile().getPath();\r
2175       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);\r
2176 \r
2177       try\r
2178       {\r
2179         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,\r
2180             "File");\r
2181         viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());\r
2182       }\r
2183       catch (Exception ex)\r
2184       {\r
2185         JOptionPane.showMessageDialog(Desktop.desktop,\r
2186                                       "Problem reading tree file",\r
2187                                       ex.getMessage(),\r
2188                                       JOptionPane.WARNING_MESSAGE);\r
2189         ex.printStackTrace();\r
2190       }\r
2191     }\r
2192   }\r
2193 \r
2194 \r
2195   public TreePanel ShowNewickTree(NewickFile nf, String title)\r
2196   {\r
2197     return ShowNewickTree(nf,title,600,500,4,5);\r
2198   }\r
2199   /**\r
2200    * DOCUMENT ME!\r
2201    *\r
2202    * @param nf DOCUMENT ME!\r
2203    * @param title DOCUMENT ME!\r
2204    *\r
2205    * @return DOCUMENT ME!\r
2206    */\r
2207   public TreePanel ShowNewickTree(NewickFile nf, String title, int w,int h,int x, int y)\r
2208   {\r
2209     TreePanel tp = null;\r
2210 \r
2211     try\r
2212     {\r
2213       nf.parse();\r
2214 \r
2215       if (nf.getTree() != null)\r
2216       {\r
2217         tp = new TreePanel(viewport,\r
2218                            viewport.getAlignment().getSequences(), nf,\r
2219                            "FromFile",\r
2220                            title);\r
2221 \r
2222         tp.setSize(w,h);\r
2223 \r
2224         if(x>0 && y>0)\r
2225           tp.setLocation(x,y);\r
2226 \r
2227 \r
2228         Desktop.addInternalFrame(tp, title, w, h);\r
2229         addTreeMenuItem(tp, title);\r
2230       }\r
2231     }\r
2232     catch (Exception ex)\r
2233     {\r
2234       ex.printStackTrace();\r
2235     }\r
2236 \r
2237     return tp;\r
2238   }\r
2239 \r
2240   class PrintThread\r
2241       extends Thread\r
2242   {\r
2243     public void run()\r
2244     {\r
2245       PrinterJob printJob = PrinterJob.getPrinterJob();\r
2246       PageFormat pf = printJob.pageDialog(printJob.defaultPage());\r
2247       printJob.setPrintable(alignPanel, pf);\r
2248 \r
2249       if (printJob.printDialog())\r
2250       {\r
2251         try\r
2252         {\r
2253           printJob.print();\r
2254         }\r
2255         catch (Exception PrintException)\r
2256         {\r
2257           PrintException.printStackTrace();\r
2258         }\r
2259       }\r
2260     }\r
2261   }\r
2262 \r
2263   /**\r
2264    * Generates menu items and listener event actions for web service clients\r
2265    *\r
2266    */\r
2267   public void BuildWebServiceMenu()\r
2268   {\r
2269     if ( (Desktop.discoverer.services != null)\r
2270         && (Desktop.discoverer.services.size() > 0))\r
2271     {\r
2272       Vector msaws = (Vector) Desktop.discoverer.services.get("MsaWS");\r
2273       Vector secstrpr = (Vector) Desktop.discoverer.services.get("SecStrPred");\r
2274       Vector wsmenu = new Vector();\r
2275       if (msaws != null)\r
2276       {\r
2277         // Add any Multiple Sequence Alignment Services\r
2278         final JMenu msawsmenu = new JMenu("Alignment");\r
2279         for (int i = 0, j = msaws.size(); i < j; i++)\r
2280         {\r
2281           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.\r
2282               get(i);\r
2283           final JMenuItem method = new JMenuItem(sh.getName());\r
2284           method.addActionListener(new ActionListener()\r
2285           {\r
2286             public void actionPerformed(ActionEvent e)\r
2287             {\r
2288               SequenceI[] msa = gatherSequencesForAlignment();\r
2289               MsaWSClient ct = new jalview.ws.MsaWSClient(sh, title, msa,\r
2290                   false, true);\r
2291 \r
2292             }\r
2293 \r
2294           });\r
2295           msawsmenu.add(method);\r
2296           // Deal with services that we know accept partial alignments.\r
2297           if (sh.getName().indexOf("lustal") > -1)\r
2298           {\r
2299             // We know that ClustalWS can accept partial alignments for refinement.\r
2300             final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");\r
2301             methodR.addActionListener(new ActionListener()\r
2302             {\r
2303               public void actionPerformed(ActionEvent e)\r
2304               {\r
2305                 SequenceI[] msa = gatherSequencesForAlignment();\r
2306                 MsaWSClient ct = new jalview.ws.MsaWSClient(sh, title, msa,\r
2307                     true, true);\r
2308 \r
2309               }\r
2310 \r
2311             });\r
2312             msawsmenu.add(methodR);\r
2313 \r
2314           }\r
2315         }\r
2316         wsmenu.add(msawsmenu);\r
2317       }\r
2318       if (secstrpr != null)\r
2319       {\r
2320         // Add any secondary structure prediction services\r
2321         final JMenu secstrmenu = new JMenu("Secondary Structure Prediction");\r
2322         for (int i = 0, j = secstrpr.size(); i < j; i++)\r
2323         {\r
2324           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)\r
2325               secstrpr.get(i);\r
2326           final JMenuItem method = new JMenuItem(sh.getName());\r
2327           method.addActionListener(new ActionListener()\r
2328           {\r
2329             public void actionPerformed(ActionEvent e)\r
2330             {\r
2331               SequenceI[] msa = gatherSeqOrMsaForSecStrPrediction();\r
2332               if (msa.length == 1)\r
2333               {\r
2334                 // Single Sequence prediction\r
2335                 jalview.ws.JPredClient ct = new jalview.ws.JPredClient(sh,\r
2336                     title, msa[0]);\r
2337               }\r
2338               else\r
2339               {\r
2340                 if (msa.length > 1)\r
2341                 {\r
2342                   // Single Sequence prediction\r
2343                   jalview.ws.JPredClient ct = new jalview.ws.JPredClient(sh,\r
2344                       title, msa);\r
2345                 }\r
2346               }\r
2347             }\r
2348           });\r
2349           secstrmenu.add(method);\r
2350         }\r
2351         wsmenu.add(secstrmenu);\r
2352       }\r
2353       this.webService.removeAll();\r
2354       for (int i = 0, j = wsmenu.size(); i < j; i++)\r
2355       {\r
2356         webService.add( (JMenu) wsmenu.get(i));\r
2357       }\r
2358     }\r
2359     else\r
2360     {\r
2361       this.webService.removeAll();\r
2362       this.webService.add(this.webServiceNoServices);\r
2363     }\r
2364     // TODO: add in rediscovery function\r
2365     // TODO: reduce code redundancy.\r
2366     // TODO: group services by location as well as function.\r
2367   }\r
2368 \r
2369 }\r