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