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