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