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