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