header updated
[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         (viewport.getSelectionGroup().getSize(false) > 3))
2171     {
2172       int s = 0;
2173       SequenceGroup sg = viewport.getSelectionGroup();
2174
2175       /* Decide if the selection is a column region */
2176       while (s < sg.getSize(false))
2177       {
2178         if ( ( (SequenceI) sg.getSequences(false).elementAt(s++)).getLength() <
2179             sg.getEndRes())
2180         {
2181           JOptionPane.showMessageDialog(Desktop.desktop,
2182                                         "The selected region to create a tree may\nonly contain residues or gaps.\n" +
2183                                         "Try using the Pad function in the edit menu,\n" +
2184                                         "or one of the multiple sequence alignment web services.",
2185                                         "Sequences in selection are not aligned",
2186                                         JOptionPane.WARNING_MESSAGE);
2187
2188           return;
2189         }
2190       }
2191
2192       title = title + " on region";
2193       tp = new TreePanel(viewport, type, pwType);
2194     }
2195     else
2196     {
2197       //are the sequences aligned?
2198       if (!viewport.alignment.isAligned())
2199       {
2200         JOptionPane.showMessageDialog(Desktop.desktop,
2201                                       "The sequences must be aligned before creating a tree.\n" +
2202                                       "Try using the Pad function in the edit menu,\n" +
2203                                       "or one of the multiple sequence alignment web services.",
2204                                       "Sequences not aligned",
2205                                       JOptionPane.WARNING_MESSAGE);
2206
2207         return;
2208       }
2209
2210       if(viewport.alignment.getHeight()<2)
2211         return;
2212
2213       tp = new TreePanel(viewport, type, pwType);
2214     }
2215
2216     addTreeMenuItem(tp, title);
2217
2218     Desktop.addInternalFrame(tp, title + " from " + this.title, 600, 500);
2219   }
2220
2221   /**
2222    * DOCUMENT ME!
2223    *
2224    * @param title DOCUMENT ME!
2225    * @param order DOCUMENT ME!
2226    */
2227   public void addSortByOrderMenuItem(String title, final AlignmentOrder order)
2228   {
2229     final JMenuItem item = new JMenuItem("by " + title);
2230     sort.add(item);
2231     item.addActionListener(new java.awt.event.ActionListener()
2232     {
2233       public void actionPerformed(ActionEvent e)
2234       {
2235         addHistoryItem(new HistoryItem("Sort", viewport.alignment,
2236                                        HistoryItem.SORT));
2237
2238         // TODO: JBPNote - have to map order entries to curent SequenceI pointers
2239         AlignmentSorter.sortBy(viewport.getAlignment(), order);
2240         alignPanel.repaint();
2241       }
2242     });
2243   }
2244
2245   /**
2246    * Maintain the Order by->Displayed Tree menu.
2247    * Creates a new menu item for a TreePanel with an appropriate
2248    * <code>jalview.analysis.AlignmentSorter</code> call. Listeners are added
2249    * to remove the menu item when the treePanel is closed, and adjust
2250    * the tree leaf to sequence mapping when the alignment is modified.
2251    * @param treePanel Displayed tree window.
2252    * @param title SortBy menu item title.
2253    */
2254   void addTreeMenuItem(final TreePanel treePanel, String title)
2255   {
2256     final JMenuItem item = new JMenuItem(title);
2257
2258     treeCount++;
2259
2260     if (treeCount == 1)
2261     {
2262       sort.add(sortByTreeMenu);
2263     }
2264
2265     sortByTreeMenu.add(item);
2266     item.addActionListener(new java.awt.event.ActionListener()
2267     {
2268       public void actionPerformed(ActionEvent e)
2269       {
2270         addHistoryItem(new HistoryItem("Tree Sort",
2271                                        viewport.alignment, HistoryItem.SORT));
2272         AlignmentSorter.sortByTree(viewport.getAlignment(),
2273                                    treePanel.getTree());
2274         alignPanel.repaint();
2275       }
2276     });
2277
2278     treePanel.addInternalFrameListener(new javax.swing.event.
2279                                        InternalFrameAdapter()
2280     {
2281       public void internalFrameClosed(
2282           javax.swing.event.InternalFrameEvent evt)
2283       {
2284         treeCount--;
2285         sortByTreeMenu.remove(item);
2286
2287         if (treeCount == 0)
2288         {
2289           sort.remove(sortByTreeMenu);
2290         }
2291       }
2292       ;
2293     });
2294   }
2295
2296   /**
2297    * Work out whether the whole set of sequences
2298    * or just the selected set will be submitted for multiple alignment.
2299    *
2300    */
2301   private jalview.datamodel.AlignmentView gatherSequencesForAlignment()
2302   {
2303     // Now, check we have enough sequences
2304     AlignmentView msa = null;
2305
2306     if ( (viewport.getSelectionGroup() != null) &&
2307         (viewport.getSelectionGroup().getSize(false) > 1))
2308     {
2309       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
2310       /*SequenceGroup seqs = viewport.getSelectionGroup();
2311       int sz;
2312       msa = new SequenceI[sz = seqs.getSize(false)];
2313
2314       for (int i = 0; i < sz; i++)
2315       {
2316         msa[i] = (SequenceI) seqs.getSequenceAt(i);
2317       } */
2318       msa = viewport.getAlignmentView(true);
2319     }
2320     else
2321     {
2322       /*Vector seqs = viewport.getAlignment().getSequences();
2323
2324       if (seqs.size() > 1)
2325       {
2326         msa = new SequenceI[seqs.size()];
2327
2328         for (int i = 0; i < seqs.size(); i++)
2329         {
2330           msa[i] = (SequenceI) seqs.elementAt(i);
2331         }
2332       }*/
2333       msa = viewport.getAlignmentView(false);
2334     }
2335     return msa;
2336   }
2337
2338   /**
2339    * Decides what is submitted to a secondary structure prediction service,
2340    * the currently selected sequence, or the currently selected alignment
2341    * (where the first sequence in the set is the one that the prediction
2342    * will be for).
2343    */
2344   AlignmentView gatherSeqOrMsaForSecStrPrediction()
2345   {
2346    AlignmentView seqs = null;
2347
2348     if ( (viewport.getSelectionGroup() != null) &&
2349         (viewport.getSelectionGroup().getSize(false) > 0))
2350     {
2351       seqs = viewport.getAlignmentView(true);
2352     }
2353     else
2354     {
2355       seqs = viewport.getAlignmentView(false);
2356     }
2357     // limit sequences - JBPNote in future - could spawn multiple prediction jobs
2358     // TODO: viewport.alignment.isAligned is a global state - the local selection may well be aligned - we preserve 2.0.8 behaviour for moment.
2359     if (!viewport.alignment.isAligned())
2360     {
2361       seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] } );
2362     }
2363     return seqs;
2364   }
2365   /**
2366    * DOCUMENT ME!
2367    *
2368    * @param e DOCUMENT ME!
2369    */
2370   protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)
2371   {
2372     // Pick the tree file
2373     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2374         getProperty(
2375             "LAST_DIRECTORY"));
2376     chooser.setFileView(new JalviewFileView());
2377     chooser.setDialogTitle("Select a newick-like tree file");
2378     chooser.setToolTipText("Load a tree file");
2379
2380     int value = chooser.showOpenDialog(null);
2381
2382     if (value == JalviewFileChooser.APPROVE_OPTION)
2383     {
2384       String choice = chooser.getSelectedFile().getPath();
2385       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
2386
2387       try
2388       {
2389         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,
2390             "File");
2391         viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
2392       }
2393       catch (Exception ex)
2394       {
2395         JOptionPane.showMessageDialog(Desktop.desktop,
2396                                       "Problem reading tree file",
2397                                       ex.getMessage(),
2398                                       JOptionPane.WARNING_MESSAGE);
2399         ex.printStackTrace();
2400       }
2401     }
2402   }
2403
2404
2405   public TreePanel ShowNewickTree(NewickFile nf, String title)
2406   {
2407     return ShowNewickTree(nf,title,600,500,4,5);
2408   }
2409   /**
2410    * DOCUMENT ME!
2411    *
2412    * @param nf DOCUMENT ME!
2413    * @param title DOCUMENT ME!
2414    *
2415    * @return DOCUMENT ME!
2416    */
2417   public TreePanel ShowNewickTree(NewickFile nf, String title, int w,int h,int x, int y)
2418   {
2419     TreePanel tp = null;
2420
2421     try
2422     {
2423       nf.parse();
2424
2425       if (nf.getTree() != null)
2426       {
2427         tp = new TreePanel(viewport,
2428                            "FromFile",
2429                            title,
2430                            nf);
2431
2432         tp.setSize(w,h);
2433
2434         if(x>0 && y>0)
2435           tp.setLocation(x,y);
2436
2437
2438         Desktop.addInternalFrame(tp, title, w, h);
2439         addTreeMenuItem(tp, title);
2440       }
2441     }
2442     catch (Exception ex)
2443     {
2444       ex.printStackTrace();
2445     }
2446
2447     return tp;
2448   }
2449
2450   class PrintThread
2451       extends Thread
2452   {
2453     public void run()
2454     {
2455       PrinterJob printJob = PrinterJob.getPrinterJob();
2456       PageFormat pf = printJob.pageDialog(printJob.defaultPage());
2457       printJob.setPrintable(alignPanel, pf);
2458
2459       if (printJob.printDialog())
2460       {
2461         try
2462         {
2463           printJob.print();
2464         }
2465         catch (Exception PrintException)
2466         {
2467           PrintException.printStackTrace();
2468         }
2469       }
2470     }
2471   }
2472
2473   /**
2474    * Generates menu items and listener event actions for web service clients
2475    *
2476    */
2477   public void BuildWebServiceMenu()
2478   {
2479     if ( (Discoverer.services != null)
2480         && (Discoverer.services.size() > 0))
2481     {
2482       Vector msaws = (Vector) Discoverer.services.get("MsaWS");
2483       Vector secstrpr = (Vector) Discoverer.services.get("SecStrPred");
2484       Vector wsmenu = new Vector();
2485       final AlignFrame af = this;
2486       if (msaws != null)
2487       {
2488         // Add any Multiple Sequence Alignment Services
2489         final JMenu msawsmenu = new JMenu("Alignment");
2490         for (int i = 0, j = msaws.size(); i < j; i++)
2491         {
2492           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.
2493               get(i);
2494           final JMenuItem method = new JMenuItem(sh.getName());
2495           method.addActionListener(new ActionListener()
2496           {
2497             public void actionPerformed(ActionEvent e)
2498             {
2499               AlignmentView msa = gatherSequencesForAlignment();
2500               new jalview.ws.MsaWSClient(sh, title, msa,
2501                   false, true, viewport.getAlignment().getDataset(), af);
2502
2503             }
2504
2505           });
2506           msawsmenu.add(method);
2507           // Deal with services that we know accept partial alignments.
2508           if (sh.getName().indexOf("lustal") > -1)
2509           {
2510             // We know that ClustalWS can accept partial alignments for refinement.
2511             final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");
2512             methodR.addActionListener(new ActionListener()
2513             {
2514               public void actionPerformed(ActionEvent e)
2515               {
2516                 AlignmentView msa = gatherSequencesForAlignment();
2517                 new jalview.ws.MsaWSClient(sh, title, msa,
2518                     true, true, viewport.getAlignment().getDataset(), af);
2519
2520               }
2521
2522             });
2523             msawsmenu.add(methodR);
2524
2525           }
2526         }
2527         wsmenu.add(msawsmenu);
2528       }
2529       if (secstrpr != null)
2530       {
2531         // Add any secondary structure prediction services
2532         final JMenu secstrmenu = new JMenu("Secondary Structure Prediction");
2533         for (int i = 0, j = secstrpr.size(); i < j; i++)
2534         {
2535           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)
2536               secstrpr.get(i);
2537           final JMenuItem method = new JMenuItem(sh.getName());
2538           method.addActionListener(new ActionListener()
2539           {
2540             public void actionPerformed(ActionEvent e)
2541             {
2542               AlignmentView msa = gatherSeqOrMsaForSecStrPrediction();
2543               if (msa.getSequences().length == 1)
2544               {
2545                 // Single Sequence prediction
2546                 new jalview.ws.JPredClient(sh, title, false, msa, af);
2547               }
2548               else
2549               {
2550                 if (msa.getSequences().length > 1)
2551                 {
2552                   // Sequence profile based prediction
2553                   new jalview.ws.JPredClient(sh,
2554                       title, true, msa, af);
2555                 }
2556               }
2557             }
2558           });
2559           secstrmenu.add(method);
2560         }
2561         wsmenu.add(secstrmenu);
2562       }
2563       this.webService.removeAll();
2564       for (int i = 0, j = wsmenu.size(); i < j; i++)
2565       {
2566         webService.add( (JMenu) wsmenu.get(i));
2567       }
2568     }
2569     else
2570     {
2571       this.webService.removeAll();
2572       this.webService.add(this.webServiceNoServices);
2573     }
2574     // TODO: add in rediscovery function
2575     // TODO: reduce code redundancy.
2576     // TODO: group services by location as well as function.
2577   }
2578
2579  /* public void vamsasStore_actionPerformed(ActionEvent e)
2580   {
2581     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2582         getProperty("LAST_DIRECTORY"));
2583
2584     chooser.setFileView(new JalviewFileView());
2585     chooser.setDialogTitle("Export to Vamsas file");
2586     chooser.setToolTipText("Export");
2587
2588     int value = chooser.showSaveDialog(this);
2589
2590     if (value == JalviewFileChooser.APPROVE_OPTION)
2591     {
2592       jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);
2593       //vs.store(chooser.getSelectedFile().getAbsolutePath()   );
2594       vs.storeJalview( chooser.getSelectedFile().getAbsolutePath(), this);
2595     }
2596   }*/
2597
2598
2599
2600
2601 public void showTranslation_actionPerformed(ActionEvent e)
2602 {
2603   SequenceI [] selection = viewport.getSelectionAsNewSequence();
2604   String [] seqstring = viewport.getViewAsString(true);
2605
2606   int s, sSize = selection.length;
2607   SequenceI [] newSeq = new SequenceI[sSize];
2608
2609   int res, resSize;
2610   StringBuffer protein;
2611   String seq;
2612   for(s=0; s<sSize; s++)
2613   {
2614     protein = new StringBuffer();
2615     seq = AlignSeq.extractGaps("-. ", seqstring[s]);
2616     resSize = seq.length();
2617     resSize -= resSize%3;
2618
2619     for(res = 0; res < resSize; res+=3)
2620     {
2621       String codon = seq.substring(res, res+3);
2622       codon = codon.replace('U', 'T');
2623       String aa = ResidueProperties.codonTranslate(codon);
2624       if(aa==null)
2625         protein.append(viewport.getGapCharacter());
2626       else if(aa.equals("STOP"))
2627         protein.append("X");
2628       else
2629         protein.append( aa );
2630     }
2631     newSeq[s] = new Sequence(selection[s].getName(),
2632                              protein.toString());
2633   }
2634
2635
2636   AlignmentI al = new Alignment(newSeq);
2637   al.setDataset(null);
2638
2639
2640   ////////////////////////////////
2641   // Copy annotations across
2642   jalview.datamodel.AlignmentAnnotation[] annotations
2643       = viewport.alignment.getAlignmentAnnotation();
2644   int a, aSize;
2645   if(annotations!=null)
2646   {
2647     for (int i = 0; i < annotations.length; i++)
2648     {
2649       if (annotations[i].label.equals("Quality") ||
2650           annotations[i].label.equals("Conservation") ||
2651           annotations[i].label.equals("Consensus"))
2652       {
2653         continue;
2654       }
2655
2656       aSize = viewport.alignment.getWidth() / 3;
2657       jalview.datamodel.Annotation[] anots =
2658           new jalview.datamodel.Annotation[aSize];
2659
2660       for (a = 0; a < viewport.alignment.getWidth(); a++)
2661       {
2662         if (annotations[i].annotations[a] == null
2663             || annotations[i].annotations[a] == null)
2664           continue;
2665
2666         anots[a / 3] = new Annotation(
2667             annotations[i].annotations[a].displayCharacter,
2668             annotations[i].annotations[a].description,
2669             annotations[i].annotations[a].secondaryStructure,
2670             annotations[i].annotations[a].value,
2671             annotations[i].annotations[a].colour);
2672       }
2673
2674       jalview.datamodel.AlignmentAnnotation aa
2675           = new jalview.datamodel.AlignmentAnnotation(annotations[i].label,
2676           annotations[i].description, anots);
2677       al.addAnnotation(aa);
2678     }
2679   }
2680
2681     AlignFrame af = new AlignFrame(al);
2682     Desktop.addInternalFrame(af, "Translation of "+this.getTitle(),
2683                              NEW_WINDOW_WIDTH,
2684                              NEW_WINDOW_HEIGHT);
2685
2686
2687    // AlignViewport newViewport = new AlignViewport(al);
2688    // AlignmentPanel ap = new AlignmentPanel(this, newViewport);
2689    // tabbedPane.add("Protein", ap);
2690    // viewports.add(newViewport);
2691   //  alignPanels.add(ap);
2692
2693     ///Dataset tab
2694   /////////////////////////
2695
2696   //  AlignViewport ds = new AlignViewport(al.getDataset());
2697   //  ds.setDataset(true);
2698   //  AlignmentPanel dap = new AlignmentPanel(this, ds);
2699   //  tabbedPane.add("Dataset", dap);
2700   //  viewports.add(ds);
2701   //  alignPanels.add(dap);
2702   /////////////////////////
2703
2704
2705 }
2706
2707 /*public void tabSelected()
2708  {
2709   int index = tabbedPane.getSelectedIndex();
2710   viewport = (AlignViewport)viewports.elementAt(index);
2711   alignPanel = (AlignmentPanel)alignPanels.elementAt(index);
2712  }*/
2713
2714 /**
2715  * DOCUMENT ME!
2716  *
2717  * @param String DOCUMENT ME!
2718  */
2719 public boolean parseFeaturesFile(String file, String type)
2720 {
2721     boolean featuresFile = false;
2722     try{
2723       featuresFile = new FeaturesFile(file, type).parse(viewport.alignment.getDataset(),
2724                                          alignPanel.seqPanel.seqCanvas.
2725                                          getFeatureRenderer().featureColours,
2726                                          false);
2727     }
2728     catch(Exception ex)
2729     {
2730       ex.printStackTrace();
2731     }
2732
2733     if(featuresFile)
2734     {
2735       viewport.showSequenceFeatures = true;
2736       showSeqFeatures.setSelected(true);
2737       alignPanel.repaint();
2738     }
2739
2740     return featuresFile;
2741 }
2742
2743 public void dragEnter(DropTargetDragEvent evt)
2744 {}
2745
2746 public void dragExit(DropTargetEvent evt)
2747 {}
2748
2749 public void dragOver(DropTargetDragEvent evt)
2750 {}
2751
2752 public void dropActionChanged(DropTargetDragEvent evt)
2753 {}
2754
2755 public void drop(DropTargetDropEvent evt)
2756 {
2757     Transferable t = evt.getTransferable();
2758     java.util.List files = null;
2759
2760     try
2761     {
2762       DataFlavor uriListFlavor = new DataFlavor("text/uri-list;class=java.lang.String");
2763       if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
2764       {
2765         //Works on Windows and MacOSX
2766         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
2767         files = (java.util.List) t.getTransferData(DataFlavor.javaFileListFlavor);
2768       }
2769       else if (t.isDataFlavorSupported(uriListFlavor))
2770       {
2771         // This is used by Unix drag system
2772         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
2773         String data = (String) t.getTransferData(uriListFlavor);
2774         files = new java.util.ArrayList(1);
2775         for (java.util.StringTokenizer st = new java.util.StringTokenizer(
2776             data,
2777             "\r\n");
2778              st.hasMoreTokens(); )
2779         {
2780           String s = st.nextToken();
2781           if (s.startsWith("#"))
2782           {
2783             // the line is a comment (as per the RFC 2483)
2784             continue;
2785           }
2786
2787           java.net.URI uri = new java.net.URI(s);
2788           java.io.File file = new java.io.File(uri);
2789           files.add(file);
2790         }
2791       }
2792     }
2793     catch (Exception e)
2794     {
2795       e.printStackTrace();
2796     }
2797     if (files != null)
2798     {
2799       try
2800       {
2801
2802         for (int i = 0; i < files.size(); i++)
2803         {
2804           loadJalviewDataFile(files.get(i).toString());
2805         }
2806       }
2807       catch (Exception ex)
2808       {
2809         ex.printStackTrace();
2810       }
2811     }
2812 }
2813
2814   // This method will attempt to load a "dropped" file first by testing
2815   // whether its and Annotation file, then features file. If both are
2816   // false then the user may have dropped an alignment file onto this
2817   // AlignFrame
2818    public void loadJalviewDataFile(String file)
2819   {
2820     try{
2821       boolean isAnnotation = new AnnotationFile().readAnnotationFile(viewport.
2822           alignment, file);
2823
2824       if (!isAnnotation)
2825       {
2826         boolean isGroupsFile = parseFeaturesFile(file,
2827                                                 AppletFormatAdapter.FILE);
2828         if (!isGroupsFile)
2829         {
2830           String format = new IdentifyFile().Identify(file, FormatAdapter.FILE);
2831           new FileLoader().LoadFile(viewport, file, FormatAdapter.FILE, format);
2832         }
2833       }
2834       else
2835       {
2836         // (isAnnotation)
2837         alignPanel.adjustAnnotationHeight();
2838       }
2839
2840     }catch(Exception ex)
2841     {
2842       ex.printStackTrace();
2843     }
2844   }
2845 }