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