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