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