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