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