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