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