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