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