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