d891b528d2ddfbbd7eb25696369a34259c8a7785
[jalview.git] / src / jalview / gui / AlignFrame.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Softwarechang
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.gui;
20
21 import java.beans.*;
22 import java.io.*;
23 import java.util.*;
24
25 import java.awt.*;
26 import java.awt.datatransfer.*;
27 import java.awt.event.*;
28 import java.awt.print.*;
29 import javax.swing.*;
30
31 import jalview.analysis.*;
32 import jalview.datamodel.*;
33 import jalview.io.*;
34 import jalview.jbgui.*;
35 import jalview.schemes.*;
36 import jalview.commands.*;
37 import jalview.ws.*;
38 import java.awt.dnd.*;
39 import javax.swing.event.ChangeListener;
40 import javax.swing.event.ChangeEvent;
41
42 /**
43  * DOCUMENT ME!
44  *
45  * @author $author$
46  * @version $Revision$
47  */
48 public class AlignFrame extends GAlignFrame implements DropTargetListener
49 {
50   /** DOCUMENT ME!! */
51   public static final int DEFAULT_WIDTH = 700;
52
53   /** DOCUMENT ME!! */
54   public static final int DEFAULT_HEIGHT = 500;
55   public AlignmentPanel alignPanel;
56
57   AlignViewport viewport;
58
59   Vector alignPanels = new Vector();
60
61
62   /** DOCUMENT ME!! */
63   String currentFileFormat = null;
64
65   String fileName = null;
66
67   private int treeCount = 0;
68
69   /**
70    * Creates a new AlignFrame object.
71    *
72    * @param al DOCUMENT ME!
73    */
74   public AlignFrame(AlignmentI al, int width, int height)
75   {
76     this(al, null, width, height);
77   }
78
79
80   /**
81    * new alignment window with hidden columns
82    * @param al AlignmentI
83    * @param hiddenColumns ColumnSelection or null
84    */
85   public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,
86                     int width, int height)
87   {
88     this.setSize(width, height);
89     viewport = new AlignViewport(al, hiddenColumns);
90
91     alignPanel = new AlignmentPanel(this, viewport);
92
93     if(al.getDataset()==null)
94     {
95       al.setDataset(null);
96     }
97
98     addAlignmentPanel(alignPanel, true);
99     init();
100   }
101
102   /**
103    * Make a new AlignFrame from exisiting alignmentPanels
104    * @param ap AlignmentPanel
105    * @param av AlignViewport
106    */
107   public AlignFrame(AlignmentPanel ap)
108   {
109     viewport = ap.av;
110     alignPanel = ap;
111     addAlignmentPanel(ap, false);
112     init();
113   }
114
115   void init()
116   {
117     this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
118
119     if (viewport.conservation == null)
120     {
121       BLOSUM62Colour.setEnabled(false);
122       conservationMenuItem.setEnabled(false);
123       modifyConservation.setEnabled(false);
124     //  PIDColour.setEnabled(false);
125     //  abovePIDThreshold.setEnabled(false);
126     //  modifyPID.setEnabled(false);
127     }
128
129     String sortby = jalview.bin.Cache.getDefault("SORT_ALIGNMENT", "No sort");
130
131     if (sortby.equals("Id"))
132       sortIDMenuItem_actionPerformed(null);
133     else if (sortby.equals("Pairwise Identity"))
134       sortPairwiseMenuItem_actionPerformed(null);
135
136     if (Desktop.desktop != null)
137    {
138      addServiceListeners();
139      setGUINucleotide(viewport.alignment.isNucleotide());
140    }
141
142    setMenusFromViewport(viewport);
143
144    if (viewport.wrapAlignment)
145    {
146      wrapMenuItem_actionPerformed(null);
147    }
148
149    addKeyListener();
150
151   }
152
153   public void setFileName(String file, String format)
154   {
155      fileName = file;
156      currentFileFormat = format;
157      reload.setEnabled(true);
158   }
159
160   void addKeyListener()
161   {
162       addKeyListener(new KeyAdapter()
163       {
164         public void keyPressed(KeyEvent evt)
165         {
166           if (viewport.cursorMode
167               && evt.getKeyCode() >= KeyEvent.VK_0
168               && evt.getKeyCode() <= KeyEvent.VK_9)
169           {
170             alignPanel.seqPanel.numberPressed(evt.getKeyChar());
171           }
172
173           switch (evt.getKeyCode())
174           {
175
176             case 27: // escape key
177               deselectAllSequenceMenuItem_actionPerformed(null);
178
179               break;
180
181             case KeyEvent.VK_DOWN:
182               if (viewport.cursorMode)
183               {
184                 alignPanel.seqPanel.moveCursor(0, 1);
185               }
186               else
187                 moveSelectedSequences(false);
188               break;
189
190             case KeyEvent.VK_UP:
191               if (viewport.cursorMode)
192               {
193                 alignPanel.seqPanel.moveCursor(0, -1);
194               }
195               else
196                 moveSelectedSequences(true);
197               break;
198
199             case KeyEvent.VK_LEFT:
200               if (viewport.cursorMode)
201               {
202                 alignPanel.seqPanel.moveCursor( -1, 0);
203               }
204               break;
205
206             case KeyEvent.VK_RIGHT:
207               if (viewport.cursorMode)
208               {
209                 alignPanel.seqPanel.moveCursor(1, 0);
210               }
211               break;
212
213             case KeyEvent.VK_SPACE:
214               if (viewport.cursorMode)
215               {
216                 alignPanel.seqPanel.insertGapAtCursor(evt.isControlDown()
217                                            || evt.isShiftDown()
218                                            || evt.isAltDown());
219               }
220               break;
221
222             case KeyEvent.VK_DELETE:
223             case KeyEvent.VK_BACK_SPACE:
224               if (!viewport.cursorMode)
225               {
226                 cut_actionPerformed(null);
227               }
228               else
229                 alignPanel.seqPanel.deleteGapAtCursor(evt.isControlDown()
230                                            || evt.isShiftDown()
231                                            || evt.isAltDown());
232
233               break;
234
235             case KeyEvent.VK_S:
236               if (viewport.cursorMode)
237               {
238                 alignPanel.seqPanel.setCursorRow();
239               }
240               break;
241             case KeyEvent.VK_C:
242               if (viewport.cursorMode && !evt.isControlDown())
243               {
244                 alignPanel.seqPanel.setCursorColumn();
245               }
246               break;
247             case KeyEvent.VK_P:
248               if (viewport.cursorMode)
249               {
250                 alignPanel.seqPanel.setCursorPosition();
251               }
252               break;
253
254             case KeyEvent.VK_ENTER:
255             case KeyEvent.VK_COMMA:
256               if (viewport.cursorMode)
257               {
258                 alignPanel.seqPanel.setCursorRowAndColumn();
259               }
260               break;
261
262             case KeyEvent.VK_Q:
263               if (viewport.cursorMode)
264               {
265                 alignPanel.seqPanel.setSelectionAreaAtCursor(true);
266               }
267               break;
268             case KeyEvent.VK_M:
269               if (viewport.cursorMode)
270               {
271                 alignPanel.seqPanel.setSelectionAreaAtCursor(false);
272               }
273               break;
274
275             case KeyEvent.VK_F2:
276               viewport.cursorMode = !viewport.cursorMode;
277               statusBar.setText("Keyboard editing mode is " +
278                                            (viewport.cursorMode ? "on" : "off"));
279               if (viewport.cursorMode)
280               {
281                 alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;
282                 alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;
283               }
284               alignPanel.seqPanel.seqCanvas.repaint();
285               break;
286
287             case KeyEvent.VK_F1:
288               try
289               {
290                 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
291                 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
292                 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
293
294                 javax.help.HelpBroker hb = hs.createHelpBroker();
295                 hb.setCurrentID("home");
296                 hb.setDisplayed(true);
297               }
298               catch (Exception ex)
299               {
300                 ex.printStackTrace();
301               }
302               break
303                   ;
304             case KeyEvent.VK_H:
305             {
306               boolean toggleSeqs = !evt.isControlDown();
307               boolean toggleCols = !evt.isShiftDown();
308
309               boolean hide = false;
310
311               SequenceGroup sg = viewport.getSelectionGroup();
312               if (toggleSeqs)
313               {
314                 if (sg != null && sg.getSize(false) != viewport.alignment.getHeight())
315                 {
316                   hideSelSequences_actionPerformed(null);
317                   hide = true;
318                 }
319                 else if (! (toggleCols && viewport.colSel.getSelected().size() > 0))
320                   showAllSeqs_actionPerformed(null);
321               }
322
323               if (toggleCols)
324               {
325                 if (viewport.colSel.getSelected().size() > 0)
326                 {
327                   hideSelColumns_actionPerformed(null);
328                   if (!toggleSeqs)
329                     viewport.selectionGroup = sg;
330                 }
331                 else if (!hide)
332                   showAllColumns_actionPerformed(null);
333               }
334               break;
335             }
336             case KeyEvent.VK_PAGE_UP:
337               if (viewport.wrapAlignment)
338                 alignPanel.scrollUp(true);
339               else
340                 alignPanel.setScrollValues(viewport.startRes,
341                                            viewport.startSeq
342                                            - viewport.endSeq + viewport.startSeq);
343               break;
344             case KeyEvent.VK_PAGE_DOWN:
345               if (viewport.wrapAlignment)
346                 alignPanel.scrollUp(false);
347               else
348                 alignPanel.setScrollValues(viewport.startRes,
349                                            viewport.startSeq
350                                            + viewport.endSeq - viewport.startSeq);
351               break;
352           }
353         }
354       });
355   }
356
357
358   public void addAlignmentPanel(final AlignmentPanel ap,
359                                 boolean newPanel)
360   {
361     ap.alignFrame = this;
362
363     alignPanels.addElement(ap);
364
365     PaintRefresher.Register(ap, ap.av.getSequenceSetId());
366
367     int aSize = alignPanels.size();
368
369     tabbedPane.setVisible(aSize>1 || ap.av.viewName!=null);
370
371     if (aSize == 1 && ap.av.viewName==null)
372     {
373       this.getContentPane().add(ap, BorderLayout.CENTER);
374     }
375     else
376     {
377       if (aSize == 2)
378       {
379         setInitialTabVisible();
380       }
381
382       expandViews.setEnabled(true);
383       gatherViews.setEnabled(true);
384       tabbedPane.addTab(ap.av.viewName==null?"Original":ap.av.viewName, ap);
385
386       ap.setVisible(false);
387     }
388
389     if(newPanel)
390     {
391       if (ap.av.padGaps)
392         ap.av.alignment.padGaps();
393       ap.av.updateConservation(ap);
394       ap.av.updateConsensus(ap);
395     }
396   }
397
398   public void setInitialTabVisible()
399   {
400     expandViews.setEnabled(true);
401     gatherViews.setEnabled(true);
402     tabbedPane.setVisible(true);
403     AlignmentPanel first = (AlignmentPanel) alignPanels.firstElement();
404     tabbedPane.addTab(first.av.viewName==null?"Original":first.av.viewName,first);
405     this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
406   }
407
408
409   public AlignViewport getViewport()
410   {
411     return viewport;
412   }
413
414   /* Set up intrinsic listeners for dynamically generated GUI bits. */
415   private void addServiceListeners()
416   {
417     final java.beans.PropertyChangeListener thisListener;
418     // Do this once to get current state
419     BuildWebServiceMenu();
420     Desktop.discoverer.addPropertyChangeListener(
421         thisListener = new java.beans.PropertyChangeListener()
422     {
423       public void propertyChange(PropertyChangeEvent evt)
424       {
425         // System.out.println("Discoverer property change.");
426         if (evt.getPropertyName().equals("services"))
427         {
428           // System.out.println("Rebuilding web service menu");
429           BuildWebServiceMenu();
430         }
431       }
432     });
433
434     addInternalFrameListener(new javax.swing.event.
435                              InternalFrameAdapter()
436     {
437       public void internalFrameClosed(
438           javax.swing.event.InternalFrameEvent evt)
439       {
440         // System.out.println("deregistering discoverer listener");
441         Desktop.discoverer.removePropertyChangeListener(thisListener);
442         closeMenuItem_actionPerformed(true);
443       }
444       ;
445     });
446   }
447
448   public void setGUINucleotide(boolean nucleotide)
449   {
450     showTranslation.setVisible( nucleotide );
451     conservationMenuItem.setEnabled( !nucleotide );
452     modifyConservation.setEnabled(   !nucleotide );
453
454     //Remember AlignFrame always starts as protein
455     if(!nucleotide)
456     {
457       calculateMenu.remove(calculateMenu.getItemCount()-2);
458     }
459   }
460
461   /**
462    * Need to call this method when tabs are selected for multiple views,
463    * or when loading from Jalview2XML.java
464    * @param av AlignViewport
465    */
466   void setMenusFromViewport(AlignViewport av)
467   {
468     padGapsMenuitem.setSelected(av.padGaps);
469     colourTextMenuItem.setSelected(av.showColourText);
470     abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
471     conservationMenuItem.setSelected(av.getConservationSelected());
472     seqLimits.setSelected(av.getShowJVSuffix());
473     idRightAlign.setSelected(av.rightAlignIds);
474     renderGapsMenuItem.setSelected(av.renderGaps);
475     wrapMenuItem.setSelected(av.wrapAlignment);
476     annotationPanelMenuItem.setState(av.showAnnotation);
477     viewBoxesMenuItem.setSelected(av.showBoxes);
478     viewTextMenuItem.setSelected(av.showText);
479
480     setColourSelected(ColourSchemeProperty.
481                       getColourName(av.getGlobalColourScheme()));
482
483     showSeqFeatures.setSelected(av.showSequenceFeatures);
484     hiddenMarkers.setState(av.showHiddenMarkers);
485     applyToAllGroups.setState(av.colourAppliesToAllGroups);
486
487     updateEditMenuBar();
488   }
489
490
491   Hashtable progressBars;
492   public void setProgressBar(String message, long id)
493   {
494     if(progressBars == null)
495       progressBars = new Hashtable();
496
497     JPanel progressPanel;
498     GridLayout layout = (GridLayout) statusPanel.getLayout();
499     if(progressBars.get( new Long(id) )!=null)
500      {
501        progressPanel = (JPanel)progressBars.get( new Long(id) );
502        statusPanel.remove(progressPanel);
503        progressBars.remove( progressPanel );
504        progressPanel = null;
505        if(message!=null)
506          statusBar.setText(message);
507
508        layout.setRows(layout.getRows() - 1);
509      }
510     else
511     {
512       progressPanel = new JPanel(new BorderLayout(10, 5));
513
514       JProgressBar progressBar = new JProgressBar();
515       progressBar.setIndeterminate(true);
516
517       progressPanel.add(new JLabel(message), BorderLayout.WEST);
518       progressPanel.add(progressBar, BorderLayout.CENTER);
519
520       layout.setRows(layout.getRows() + 1);
521       statusPanel.add(progressPanel);
522
523       progressBars.put(new Long(id), progressPanel);
524     }
525
526     validate();
527   }
528
529
530
531
532   /*
533    Added so Castor Mapping file can obtain Jalview Version
534   */
535   public String getVersion()
536   {
537     return  jalview.bin.Cache.getProperty("VERSION");
538   }
539
540   public FeatureRenderer getFeatureRenderer()
541   {
542     return alignPanel.seqPanel.seqCanvas.getFeatureRenderer();
543   }
544
545
546   public void fetchSequence_actionPerformed(ActionEvent e)
547   {
548     new SequenceFetcher(this);
549   }
550
551   public void addFromFile_actionPerformed(ActionEvent e)
552   {
553     Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
554   }
555
556   public void reload_actionPerformed(ActionEvent e)
557   {
558     if(fileName!=null)
559     {
560       if(currentFileFormat.equals("Jalview"))
561       {
562         JInternalFrame [] frames = Desktop.desktop.getAllFrames();
563         for(int i=0; i<frames.length; i++)
564         {
565           if (frames[i] instanceof AlignFrame
566               && frames[i] != this
567               && ( (AlignFrame) frames[i]).fileName.equals(fileName))
568           {
569             try{
570               frames[i].setSelected(true);
571               Desktop.instance.closeAssociatedWindows();
572             }catch(java.beans.PropertyVetoException ex){}
573           }
574
575         }
576         Desktop.instance.closeAssociatedWindows();
577
578       }
579       else
580       {
581         viewport.alignment.deleteAllGroups();
582         viewport.sequenceColours=null;
583         while (viewport.alignment.getHeight() > 0)
584         {
585           viewport.alignment.deleteSequence(0);
586         }
587
588         viewport.historyList.clear();
589         viewport.redoList.clear();
590         Alignment dset = viewport.alignment.getDataset();
591         while (dset.getHeight() > 0)
592         {
593           dset.deleteSequence(0);
594         }
595
596         firePropertyChange("Alignment", null, null);
597
598         updateEditMenuBar();
599       }
600
601       FileLoader loader = new FileLoader();
602       String protocol = fileName.startsWith("http:")? "URL":"File";
603       loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
604
605     }
606   }
607
608
609   public void addFromText_actionPerformed(ActionEvent e)
610   {
611     Desktop.instance.inputTextboxMenuItem_actionPerformed(viewport);
612   }
613
614   public void addFromURL_actionPerformed(ActionEvent e)
615   {
616     Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
617   }
618
619
620   public void save_actionPerformed(ActionEvent e)
621   {
622     if(fileName==null || currentFileFormat==null)
623       saveAs_actionPerformed(null);
624     else
625       saveAlignment(fileName, currentFileFormat);
626   }
627
628   /**
629    * DOCUMENT ME!
630    *
631    * @param e DOCUMENT ME!
632    */
633   public void saveAs_actionPerformed(ActionEvent e)
634   {
635     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
636         getProperty( "LAST_DIRECTORY"),
637         new String[]
638         { "fa, fasta, fastq", "aln", "pfam", "msf", "pir", "blc","jar" },
639         new String[]
640         { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview" },
641         currentFileFormat,
642         false);
643
644
645     chooser.setFileView(new JalviewFileView());
646     chooser.setDialogTitle("Save Alignment to file");
647     chooser.setToolTipText("Save");
648
649     int value = chooser.showSaveDialog(this);
650
651     if (value == JalviewFileChooser.APPROVE_OPTION)
652     {
653         currentFileFormat = chooser.getSelectedFormat();
654         if (currentFileFormat == null)
655         {
656           JOptionPane.showInternalMessageDialog(Desktop.desktop,
657                                                 "You must select a file format before saving!",
658                                                 "File format not specified",
659                                                 JOptionPane.WARNING_MESSAGE);
660           value = chooser.showSaveDialog(this);
661           return;
662         }
663
664         fileName = chooser.getSelectedFile().getPath();
665
666       jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT",
667                                     currentFileFormat);
668
669       jalview.bin.Cache.setProperty("LAST_DIRECTORY", fileName);
670
671       saveAlignment(fileName, currentFileFormat);
672     }
673   }
674
675   public boolean saveAlignment(String file, String format)
676   {
677     if (format.equalsIgnoreCase("Jalview"))
678     {
679       String shortName = title;
680
681       if (shortName.indexOf(java.io.File.separatorChar) > -1)
682       {
683         shortName = shortName.substring(shortName.lastIndexOf(
684             java.io.File.separatorChar) + 1);
685       }
686
687       new Jalview2XML().SaveAlignment(this, file, shortName);
688
689       statusBar.setText("Successfully saved to file: "
690                           +fileName+" in "
691                           +format +" format.");
692
693
694       // USE Jalview2XML to save this file
695       return true;
696     }
697     else
698     {
699
700       String[] omitHidden = null;
701
702       if (viewport.hasHiddenColumns)
703       {
704         int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
705             "The Alignment contains hidden columns."
706             + "\nDo you want to save only the visible alignment?",
707             "Save / Omit Hidden Columns",
708             JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
709
710         if (reply == JOptionPane.YES_OPTION)
711           omitHidden = viewport.getViewAsString(false);
712       }
713
714       String output = new FormatAdapter().formatSequences(
715           format,
716           viewport.alignment.getSequencesArray(),
717           omitHidden);
718
719       if (output == null)
720       {
721         return false;
722       }
723
724       try
725       {
726         java.io.PrintWriter out = new java.io.PrintWriter(
727             new java.io.FileWriter(file));
728
729         out.print(output);
730         out.close();
731         this.setTitle(file);
732         statusBar.setText("Successfully saved to file: "
733                           +fileName+" in "
734                           +format +" format.");
735         return true;
736       }
737       catch (Exception ex)
738       {
739         ex.printStackTrace();
740       }
741     }
742     return false;
743   }
744
745   /**
746    * DOCUMENT ME!
747    *
748    * @param e DOCUMENT ME!
749    */
750   protected void outputText_actionPerformed(ActionEvent e)
751   {
752     String [] omitHidden = null;
753
754     if(viewport.hasHiddenColumns)
755     {
756       int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
757           "The Alignment contains hidden columns."
758       +"\nDo you want to output only the visible alignment?",
759       "Save / Omit Hidden Columns",
760       JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
761
762       if(reply==JOptionPane.YES_OPTION)
763       {
764         omitHidden = viewport.getViewAsString(false);
765       }
766     }
767
768     CutAndPasteTransfer cap = new CutAndPasteTransfer();
769     cap.setForInput(null);
770     Desktop.addInternalFrame(cap,
771                              "Alignment output - " + e.getActionCommand(), 600,
772                              500);
773
774
775     cap.setText(new FormatAdapter().formatSequences(
776         e.getActionCommand(),
777         viewport.alignment.getSequencesArray(),
778         omitHidden));
779   }
780
781   /**
782    * DOCUMENT ME!
783    *
784    * @param e DOCUMENT ME!
785    */
786   protected void htmlMenuItem_actionPerformed(ActionEvent e)
787   {
788     new HTMLOutput(viewport,
789                    alignPanel.seqPanel.seqCanvas.getSequenceRenderer(),
790         alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
791   }
792
793   public void createImageMap(File file, String image)
794   {
795     alignPanel.makePNGImageMap(file, image);
796   }
797
798   /**
799    * DOCUMENT ME!
800    *
801    * @param e DOCUMENT ME!
802    */
803   public void createPNG(File f)
804   {
805     alignPanel.makePNG(f);
806   }
807
808   /**
809    * DOCUMENT ME!
810    *
811    * @param e DOCUMENT ME!
812    */
813   public void createEPS(File f)
814   {
815     alignPanel.makeEPS(f);
816   }
817
818   /**
819    * DOCUMENT ME!
820    *
821    * @param e DOCUMENT ME!
822    */
823   public void printMenuItem_actionPerformed(ActionEvent e)
824   {
825     //Putting in a thread avoids Swing painting problems
826     PrintThread thread = new PrintThread();
827     thread.start();
828   }
829
830   public void exportFeatures_actionPerformed(ActionEvent e)
831   {
832     new AnnotationExporter().exportFeatures(alignPanel);
833   }
834
835
836   public void exportAnnotations_actionPerformed(ActionEvent e)
837   {
838     new AnnotationExporter().exportAnnotations(
839       alignPanel,
840       viewport.alignment.getAlignmentAnnotation()
841         );
842   }
843
844
845   public void associatedData_actionPerformed(ActionEvent e)
846   {
847     // Pick the tree file
848     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
849         getProperty(
850             "LAST_DIRECTORY"));
851     chooser.setFileView(new JalviewFileView());
852     chooser.setDialogTitle("Load Jalview Annotations or Features File");
853     chooser.setToolTipText("Load Jalview Annotations / Features file");
854
855     int value = chooser.showOpenDialog(null);
856
857     if (value == JalviewFileChooser.APPROVE_OPTION)
858     {
859       String choice = chooser.getSelectedFile().getPath();
860       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
861       loadJalviewDataFile(choice);
862     }
863
864   }
865
866
867   /**
868    * DOCUMENT ME!
869    *
870    * @param e DOCUMENT ME!
871    */
872   public void closeMenuItem_actionPerformed(boolean closeAllTabs)
873   {
874     if(alignPanels!=null && alignPanels.size()<2)
875       closeAllTabs = true;
876
877     try
878     {
879       if(alignPanels!=null)
880       {
881         if (closeAllTabs)
882           for (int i = 0; i < alignPanels.size(); i++)
883           {
884             AlignmentPanel ap = (AlignmentPanel) alignPanels.elementAt(i);
885             PaintRefresher.RemoveComponent(ap.seqPanel.seqCanvas);
886             PaintRefresher.RemoveComponent(ap.idPanel.idCanvas);
887             PaintRefresher.RemoveComponent(ap);
888           }
889         else
890         {
891           int index = tabbedPane.getSelectedIndex();
892
893           tabbedPane.removeTabAt(index);
894           alignPanels.removeElement(alignPanel);
895           PaintRefresher.RemoveComponent(alignPanel.seqPanel.seqCanvas);
896           PaintRefresher.RemoveComponent(alignPanel.idPanel.idCanvas);
897           PaintRefresher.RemoveComponent(alignPanel);
898           alignPanel = null;
899           viewport = null;
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 = "View 1";
1733
1734     newap.av.historyList = viewport.historyList;
1735     newap.av.redoList = viewport.redoList;
1736     newap.av.viewName = "View " +
1737         (Desktop.getViewCount(viewport.getSequenceSetId()) + 1);
1738
1739     addAlignmentPanel(newap, false);
1740
1741     if(alignPanels.size()==2)
1742     {
1743       viewport.gatherViewsHere = true;
1744     }
1745     tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
1746   }
1747
1748   public void expandViews_actionPerformed(ActionEvent e)
1749   {
1750         Desktop.instance.explodeViews(this);
1751   }
1752
1753   public void gatherViews_actionPerformed(ActionEvent e)
1754   {
1755     Desktop.instance.gatherViews(this);
1756   }
1757
1758
1759
1760   /**
1761    * DOCUMENT ME!
1762    *
1763    * @param e DOCUMENT ME!
1764    */
1765   public void font_actionPerformed(ActionEvent e)
1766   {
1767     new FontChooser(alignPanel);
1768   }
1769
1770
1771   /**
1772    * DOCUMENT ME!
1773    *
1774    * @param e DOCUMENT ME!
1775    */
1776   protected void seqLimit_actionPerformed(ActionEvent e)
1777   {
1778     viewport.setShowJVSuffix(seqLimits.isSelected());
1779
1780     alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel.calculateIdWidth());
1781     alignPanel.repaint();
1782   }
1783
1784   public void idRightAlign_actionPerformed(ActionEvent e)
1785   {
1786     viewport.rightAlignIds = idRightAlign.isSelected();
1787     alignPanel.repaint();
1788   }
1789
1790
1791
1792   /**
1793    * DOCUMENT ME!
1794    *
1795    * @param e DOCUMENT ME!
1796    */
1797   protected void colourTextMenuItem_actionPerformed(ActionEvent e)
1798   {
1799     viewport.setColourText(colourTextMenuItem.isSelected());
1800     alignPanel.repaint();
1801   }
1802
1803   /**
1804    * DOCUMENT ME!
1805    *
1806    * @param e DOCUMENT ME!
1807    */
1808   public void wrapMenuItem_actionPerformed(ActionEvent e)
1809   {
1810     scaleAbove.setVisible(wrapMenuItem.isSelected());
1811     scaleLeft.setVisible(wrapMenuItem.isSelected());
1812     scaleRight.setVisible(wrapMenuItem.isSelected());
1813     viewport.setWrapAlignment(wrapMenuItem.isSelected());
1814     alignPanel.setWrapAlignment(wrapMenuItem.isSelected());
1815   }
1816
1817   public void showAllSeqs_actionPerformed(ActionEvent e)
1818   {
1819     viewport.showAllHiddenSeqs();
1820   }
1821
1822   public void showAllColumns_actionPerformed(ActionEvent e)
1823   {
1824     viewport.showAllHiddenColumns();
1825     repaint();
1826   }
1827
1828   public void hideSelSequences_actionPerformed(ActionEvent e)
1829   {
1830     viewport.hideAllSelectedSeqs();
1831     alignPanel.repaint();
1832   }
1833
1834   public void hideSelColumns_actionPerformed(ActionEvent e)
1835   {
1836     viewport.hideSelectedColumns();
1837     alignPanel.repaint();
1838   }
1839
1840   public void hiddenMarkers_actionPerformed(ActionEvent e)
1841   {
1842     viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
1843     repaint();
1844   }
1845
1846   /**
1847    * DOCUMENT ME!
1848    *
1849    * @param e DOCUMENT ME!
1850    */
1851   protected void scaleAbove_actionPerformed(ActionEvent e)
1852   {
1853     viewport.setScaleAboveWrapped(scaleAbove.isSelected());
1854     alignPanel.repaint();
1855   }
1856
1857   /**
1858    * DOCUMENT ME!
1859    *
1860    * @param e DOCUMENT ME!
1861    */
1862   protected void scaleLeft_actionPerformed(ActionEvent e)
1863   {
1864     viewport.setScaleLeftWrapped(scaleLeft.isSelected());
1865     alignPanel.repaint();
1866   }
1867
1868   /**
1869    * DOCUMENT ME!
1870    *
1871    * @param e DOCUMENT ME!
1872    */
1873   protected void scaleRight_actionPerformed(ActionEvent e)
1874   {
1875     viewport.setScaleRightWrapped(scaleRight.isSelected());
1876     alignPanel.repaint();
1877   }
1878
1879   /**
1880    * DOCUMENT ME!
1881    *
1882    * @param e DOCUMENT ME!
1883    */
1884   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
1885   {
1886     viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
1887     alignPanel.repaint();
1888   }
1889
1890   /**
1891    * DOCUMENT ME!
1892    *
1893    * @param e DOCUMENT ME!
1894    */
1895   public void viewTextMenuItem_actionPerformed(ActionEvent e)
1896   {
1897     viewport.setShowText(viewTextMenuItem.isSelected());
1898     alignPanel.repaint();
1899   }
1900
1901   /**
1902    * DOCUMENT ME!
1903    *
1904    * @param e DOCUMENT ME!
1905    */
1906   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
1907   {
1908     viewport.setRenderGaps(renderGapsMenuItem.isSelected());
1909     alignPanel.repaint();
1910   }
1911
1912
1913   public FeatureSettings featureSettings;
1914   public void featureSettings_actionPerformed(ActionEvent e)
1915   {
1916     if(featureSettings !=null )
1917     {
1918       featureSettings.close();
1919       featureSettings = null;
1920     }
1921     featureSettings = new FeatureSettings(this);
1922   }
1923
1924   /**
1925    * DOCUMENT ME!
1926    *
1927    * @param evt DOCUMENT ME!
1928    */
1929   public void showSeqFeatures_actionPerformed(ActionEvent evt)
1930   {
1931     viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
1932     alignPanel.repaint();
1933     if (alignPanel.getOverviewPanel() != null)
1934     {
1935       alignPanel.getOverviewPanel().updateOverviewImage();
1936     }
1937   }
1938
1939   /**
1940    * DOCUMENT ME!
1941    *
1942    * @param e DOCUMENT ME!
1943    */
1944   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
1945   {
1946     viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());
1947     alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());
1948   }
1949
1950   /**
1951    * DOCUMENT ME!
1952    *
1953    * @param e DOCUMENT ME!
1954    */
1955   public void overviewMenuItem_actionPerformed(ActionEvent e)
1956   {
1957     if (alignPanel.overviewPanel != null)
1958     {
1959       return;
1960     }
1961
1962     JInternalFrame frame = new JInternalFrame();
1963     OverviewPanel overview = new OverviewPanel(alignPanel);
1964     frame.setContentPane(overview);
1965     Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),
1966                              frame.getWidth(), frame.getHeight());
1967     frame.pack();
1968     frame.setLayer(JLayeredPane.PALETTE_LAYER);
1969     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
1970     {
1971       public void internalFrameClosed(
1972           javax.swing.event.InternalFrameEvent evt)
1973       {
1974         alignPanel.setOverviewPanel(null);
1975       }
1976       ;
1977     });
1978
1979     alignPanel.setOverviewPanel(overview);
1980   }
1981
1982   public void textColour_actionPerformed(ActionEvent e)
1983   {
1984     new TextColourChooser().chooseColour(alignPanel, null);
1985   }
1986
1987   /**
1988    * DOCUMENT ME!
1989    *
1990    * @param e DOCUMENT ME!
1991    */
1992   protected void noColourmenuItem_actionPerformed(ActionEvent e)
1993   {
1994     changeColour(null);
1995   }
1996
1997   /**
1998    * DOCUMENT ME!
1999    *
2000    * @param e DOCUMENT ME!
2001    */
2002   public void clustalColour_actionPerformed(ActionEvent e)
2003   {
2004     changeColour(new ClustalxColourScheme(
2005         viewport.alignment.getSequences(), viewport.alignment.getWidth()));
2006   }
2007
2008   /**
2009    * DOCUMENT ME!
2010    *
2011    * @param e DOCUMENT ME!
2012    */
2013   public void zappoColour_actionPerformed(ActionEvent e)
2014   {
2015     changeColour(new ZappoColourScheme());
2016   }
2017
2018   /**
2019    * DOCUMENT ME!
2020    *
2021    * @param e DOCUMENT ME!
2022    */
2023   public void taylorColour_actionPerformed(ActionEvent e)
2024   {
2025     changeColour(new TaylorColourScheme());
2026   }
2027
2028   /**
2029    * DOCUMENT ME!
2030    *
2031    * @param e DOCUMENT ME!
2032    */
2033   public void hydrophobicityColour_actionPerformed(ActionEvent e)
2034   {
2035     changeColour(new HydrophobicColourScheme());
2036   }
2037
2038   /**
2039    * DOCUMENT ME!
2040    *
2041    * @param e DOCUMENT ME!
2042    */
2043   public void helixColour_actionPerformed(ActionEvent e)
2044   {
2045     changeColour(new HelixColourScheme());
2046   }
2047
2048   /**
2049    * DOCUMENT ME!
2050    *
2051    * @param e DOCUMENT ME!
2052    */
2053   public void strandColour_actionPerformed(ActionEvent e)
2054   {
2055     changeColour(new StrandColourScheme());
2056   }
2057
2058   /**
2059    * DOCUMENT ME!
2060    *
2061    * @param e DOCUMENT ME!
2062    */
2063   public void turnColour_actionPerformed(ActionEvent e)
2064   {
2065     changeColour(new TurnColourScheme());
2066   }
2067
2068   /**
2069    * DOCUMENT ME!
2070    *
2071    * @param e DOCUMENT ME!
2072    */
2073   public void buriedColour_actionPerformed(ActionEvent e)
2074   {
2075     changeColour(new BuriedColourScheme());
2076   }
2077
2078   /**
2079    * DOCUMENT ME!
2080    *
2081    * @param e DOCUMENT ME!
2082    */
2083   public void nucleotideColour_actionPerformed(ActionEvent e)
2084   {
2085     changeColour(new NucleotideColourScheme());
2086   }
2087
2088   public void annotationColour_actionPerformed(ActionEvent e)
2089   {
2090     new AnnotationColourChooser(viewport, alignPanel);
2091   }
2092
2093
2094   /**
2095    * DOCUMENT ME!
2096    *
2097    * @param e DOCUMENT ME!
2098    */
2099   protected void applyToAllGroups_actionPerformed(ActionEvent e)
2100   {
2101     viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
2102   }
2103
2104   /**
2105    * DOCUMENT ME!
2106    *
2107    * @param cs DOCUMENT ME!
2108    */
2109   public void changeColour(ColourSchemeI cs)
2110   {
2111     int threshold = 0;
2112
2113     if(cs!=null)
2114     {
2115       if (viewport.getAbovePIDThreshold())
2116       {
2117         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,
2118                                                    "Background");
2119
2120         cs.setThreshold(threshold,
2121                         viewport.getIgnoreGapsConsensus());
2122
2123         viewport.setGlobalColourScheme(cs);
2124       }
2125       else
2126       {
2127         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2128       }
2129
2130       if (viewport.getConservationSelected())
2131       {
2132
2133         Alignment al = (Alignment) viewport.alignment;
2134         Conservation c = new Conservation("All",
2135                                           ResidueProperties.propHash, 3,
2136                                           al.getSequences(), 0,
2137                                           al.getWidth() - 1);
2138
2139         c.calculate();
2140         c.verdict(false, viewport.ConsPercGaps);
2141
2142         cs.setConservation(c);
2143
2144         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,
2145             "Background"));
2146       }
2147       else
2148       {
2149         cs.setConservation(null);
2150       }
2151
2152       cs.setConsensus(viewport.hconsensus);
2153     }
2154
2155     viewport.setGlobalColourScheme(cs);
2156
2157     if (viewport.getColourAppliesToAllGroups())
2158     {
2159       Vector groups = viewport.alignment.getGroups();
2160
2161       for (int i = 0; i < groups.size(); i++)
2162       {
2163         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
2164
2165         if (cs == null)
2166         {
2167           sg.cs = null;
2168           continue;
2169         }
2170
2171         if (cs instanceof ClustalxColourScheme)
2172         {
2173           sg.cs = new ClustalxColourScheme(
2174               sg.getSequences(true), sg.getWidth());
2175         }
2176         else if (cs instanceof UserColourScheme)
2177         {
2178           sg.cs = new UserColourScheme( ( (UserColourScheme) cs).getColours());
2179         }
2180         else
2181         {
2182           try
2183           {
2184             sg.cs = (ColourSchemeI) cs.getClass().newInstance();
2185           }
2186           catch (Exception ex)
2187           {
2188           }
2189         }
2190
2191         if (viewport.getAbovePIDThreshold()
2192             || cs instanceof PIDColourScheme
2193             || cs instanceof Blosum62ColourScheme)
2194         {
2195          sg.cs.setThreshold(threshold,
2196                 viewport.getIgnoreGapsConsensus());
2197
2198          sg.cs.setConsensus(AAFrequency.calculate(
2199              sg.getSequences(true), sg.getStartRes(),
2200              sg.getEndRes()+1));
2201        }
2202         else
2203           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2204
2205
2206         if (viewport.getConservationSelected())
2207         {
2208           Conservation c = new Conservation("Group",
2209                                             ResidueProperties.propHash, 3,
2210                                             sg.getSequences(true),
2211                                             sg.getStartRes(),
2212                                             sg.getEndRes()+1);
2213           c.calculate();
2214           c.verdict(false, viewport.ConsPercGaps);
2215           sg.cs.setConservation(c);
2216         }
2217         else
2218           sg.cs.setConservation(null);
2219       }
2220     }
2221
2222     if (alignPanel.getOverviewPanel() != null)
2223     {
2224       alignPanel.getOverviewPanel().updateOverviewImage();
2225     }
2226
2227     alignPanel.repaint();
2228   }
2229
2230   /**
2231    * DOCUMENT ME!
2232    *
2233    * @param e DOCUMENT ME!
2234    */
2235   protected void modifyPID_actionPerformed(ActionEvent e)
2236   {
2237     if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme!=null)
2238     {
2239       SliderPanel.setPIDSliderSource(alignPanel,
2240                                      viewport.getGlobalColourScheme(),
2241                                      "Background");
2242       SliderPanel.showPIDSlider();
2243     }
2244   }
2245
2246   /**
2247    * DOCUMENT ME!
2248    *
2249    * @param e DOCUMENT ME!
2250    */
2251   protected void modifyConservation_actionPerformed(ActionEvent e)
2252   {
2253     if (viewport.getConservationSelected() && viewport.globalColourScheme!=null)
2254     {
2255       SliderPanel.setConservationSlider(alignPanel,
2256                                         viewport.globalColourScheme,
2257                                         "Background");
2258       SliderPanel.showConservationSlider();
2259     }
2260   }
2261
2262   /**
2263    * DOCUMENT ME!
2264    *
2265    * @param e DOCUMENT ME!
2266    */
2267   protected void conservationMenuItem_actionPerformed(ActionEvent e)
2268   {
2269     viewport.setConservationSelected(conservationMenuItem.isSelected());
2270
2271     viewport.setAbovePIDThreshold(false);
2272     abovePIDThreshold.setSelected(false);
2273
2274     changeColour(viewport.getGlobalColourScheme());
2275
2276     modifyConservation_actionPerformed(null);
2277   }
2278
2279   /**
2280    * DOCUMENT ME!
2281    *
2282    * @param e DOCUMENT ME!
2283    */
2284   public void abovePIDThreshold_actionPerformed(ActionEvent e)
2285   {
2286     viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());
2287
2288     conservationMenuItem.setSelected(false);
2289     viewport.setConservationSelected(false);
2290
2291     changeColour(viewport.getGlobalColourScheme());
2292
2293     modifyPID_actionPerformed(null);
2294   }
2295
2296   /**
2297    * DOCUMENT ME!
2298    *
2299    * @param e DOCUMENT ME!
2300    */
2301   public void userDefinedColour_actionPerformed(ActionEvent e)
2302   {
2303     if (e.getActionCommand().equals("User Defined..."))
2304     {
2305       new UserDefinedColours(alignPanel, null);
2306     }
2307     else
2308     {
2309       UserColourScheme udc = (UserColourScheme) UserDefinedColours.
2310           getUserColourSchemes().get(e.getActionCommand());
2311
2312       changeColour(udc);
2313     }
2314   }
2315
2316   public void updateUserColourMenu()
2317   {
2318
2319     Component[] menuItems = colourMenu.getMenuComponents();
2320     int i, iSize = menuItems.length;
2321     for (i = 0; i < iSize; i++)
2322     {
2323       if (menuItems[i].getName() != null &&
2324           menuItems[i].getName().equals("USER_DEFINED"))
2325       {
2326         colourMenu.remove(menuItems[i]);
2327         iSize--;
2328       }
2329     }
2330     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
2331     {
2332       java.util.Enumeration userColours = jalview.gui.UserDefinedColours.
2333           getUserColourSchemes().keys();
2334
2335       while (userColours.hasMoreElements())
2336       {
2337         final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(userColours.
2338             nextElement().toString());
2339         radioItem.setName("USER_DEFINED");
2340         radioItem.addMouseListener(new MouseAdapter()
2341             {
2342               public void mousePressed(MouseEvent evt)
2343               {
2344                 if(evt.isControlDown() || SwingUtilities.isRightMouseButton(evt))
2345                 {
2346                   radioItem.removeActionListener(radioItem.getActionListeners()[0]);
2347
2348                   int option = JOptionPane.showInternalConfirmDialog(jalview.gui.Desktop.desktop,
2349                       "Remove from default list?",
2350                       "Remove user defined colour",
2351                       JOptionPane.YES_NO_OPTION);
2352                   if(option == JOptionPane.YES_OPTION)
2353                   {
2354                     jalview.gui.UserDefinedColours.removeColourFromDefaults(radioItem.getText());
2355                     colourMenu.remove(radioItem);
2356                   }
2357                   else
2358                     radioItem.addActionListener(new ActionListener()
2359                     {
2360                       public void actionPerformed(ActionEvent evt)
2361                       {
2362                         userDefinedColour_actionPerformed(evt);
2363                       }
2364                     });
2365                 }
2366               }
2367             });
2368         radioItem.addActionListener(new ActionListener()
2369         {
2370           public void actionPerformed(ActionEvent evt)
2371           {
2372             userDefinedColour_actionPerformed(evt);
2373           }
2374         });
2375
2376         colourMenu.insert(radioItem, 15);
2377         colours.add(radioItem);
2378       }
2379     }
2380   }
2381
2382   /**
2383    * DOCUMENT ME!
2384    *
2385    * @param e DOCUMENT ME!
2386    */
2387   public void PIDColour_actionPerformed(ActionEvent e)
2388   {
2389     changeColour(new PIDColourScheme());
2390   }
2391
2392   /**
2393    * DOCUMENT ME!
2394    *
2395    * @param e DOCUMENT ME!
2396    */
2397   public void BLOSUM62Colour_actionPerformed(ActionEvent e)
2398   {
2399     changeColour(new Blosum62ColourScheme());
2400   }
2401
2402   /**
2403    * DOCUMENT ME!
2404    *
2405    * @param e DOCUMENT ME!
2406    */
2407   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
2408   {
2409     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2410     AlignmentSorter.sortByPID(viewport.getAlignment(),
2411                               viewport.getAlignment().getSequenceAt(0));
2412     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder, viewport.alignment));
2413     alignPanel.repaint();
2414   }
2415
2416   /**
2417    * DOCUMENT ME!
2418    *
2419    * @param e DOCUMENT ME!
2420    */
2421   public void sortIDMenuItem_actionPerformed(ActionEvent e)
2422   {
2423     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2424     AlignmentSorter.sortByID(viewport.getAlignment());
2425     addHistoryItem(new OrderCommand("ID Sort", oldOrder, viewport.alignment));
2426     alignPanel.repaint();
2427   }
2428
2429   /**
2430    * DOCUMENT ME!
2431    *
2432    * @param e DOCUMENT ME!
2433    */
2434   public void sortGroupMenuItem_actionPerformed(ActionEvent e)
2435   {
2436     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2437     AlignmentSorter.sortByGroup(viewport.getAlignment());
2438     addHistoryItem(new OrderCommand("Group Sort", oldOrder, viewport.alignment));
2439
2440     alignPanel.repaint();
2441   }
2442
2443   /**
2444    * DOCUMENT ME!
2445    *
2446    * @param e DOCUMENT ME!
2447    */
2448   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
2449   {
2450     new RedundancyPanel(alignPanel, this);
2451   }
2452
2453
2454   /**
2455    * DOCUMENT ME!
2456    *
2457    * @param e DOCUMENT ME!
2458    */
2459   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
2460   {
2461     if ( (viewport.getSelectionGroup() == null) ||
2462         (viewport.getSelectionGroup().getSize(false) < 2))
2463     {
2464       JOptionPane.showInternalMessageDialog(this,
2465                                             "You must select at least 2 sequences.",
2466                                             "Invalid Selection",
2467                                             JOptionPane.WARNING_MESSAGE);
2468     }
2469     else
2470     {
2471       JInternalFrame frame = new JInternalFrame();
2472       frame.setContentPane(new PairwiseAlignPanel(viewport));
2473       Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);
2474     }
2475   }
2476
2477   /**
2478    * DOCUMENT ME!
2479    *
2480    * @param e DOCUMENT ME!
2481    */
2482   public void PCAMenuItem_actionPerformed(ActionEvent e)
2483   {
2484     if ( ( (viewport.getSelectionGroup() != null) &&
2485           (viewport.getSelectionGroup().getSize(false) < 4) &&
2486           (viewport.getSelectionGroup().getSize(false) > 0)) ||
2487         (viewport.getAlignment().getHeight() < 4))
2488     {
2489       JOptionPane.showInternalMessageDialog(this,
2490                                             "Principal component analysis must take\n" +
2491                                             "at least 4 input sequences.",
2492                                             "Sequence selection insufficient",
2493                                             JOptionPane.WARNING_MESSAGE);
2494
2495       return;
2496     }
2497
2498      new PCAPanel(viewport);
2499   }
2500
2501
2502   public void autoCalculate_actionPerformed(ActionEvent e)
2503   {
2504     viewport.autoCalculateConsensus = autoCalculate.isSelected();
2505     if(viewport.autoCalculateConsensus)
2506     {
2507       viewport.firePropertyChange("alignment",
2508                                   null,
2509                                   viewport.getAlignment().getSequences());
2510     }
2511   }
2512
2513
2514   /**
2515    * DOCUMENT ME!
2516    *
2517    * @param e DOCUMENT ME!
2518    */
2519   public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
2520   {
2521     NewTreePanel("AV", "PID", "Average distance tree using PID");
2522   }
2523
2524   /**
2525    * DOCUMENT ME!
2526    *
2527    * @param e DOCUMENT ME!
2528    */
2529   public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
2530   {
2531     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
2532   }
2533
2534   /**
2535    * DOCUMENT ME!
2536    *
2537    * @param e DOCUMENT ME!
2538    */
2539   protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
2540   {
2541     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
2542   }
2543
2544   /**
2545    * DOCUMENT ME!
2546    *
2547    * @param e DOCUMENT ME!
2548    */
2549   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
2550   {
2551     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
2552   }
2553
2554   /**
2555    * DOCUMENT ME!
2556    *
2557    * @param type DOCUMENT ME!
2558    * @param pwType DOCUMENT ME!
2559    * @param title DOCUMENT ME!
2560    */
2561   void NewTreePanel(String type, String pwType, String title)
2562   {
2563     TreePanel tp;
2564
2565     if (viewport.getSelectionGroup() != null) {
2566       if (viewport.getSelectionGroup().getSize(false) < 3) {
2567         JOptionPane.showMessageDialog(Desktop.desktop,
2568                                       "You need to have more than two sequences selected to build a tree!",
2569                                       "Not enough sequences",
2570                                       JOptionPane.WARNING_MESSAGE);
2571         return;
2572       }
2573
2574       int s = 0;
2575       SequenceGroup sg = viewport.getSelectionGroup();
2576
2577       /* Decide if the selection is a column region */
2578       while (s < sg.getSize(false))
2579       {
2580         if ( ( (SequenceI) sg.getSequences(false).elementAt(s++)).getLength() <
2581             sg.getEndRes())
2582         {
2583           JOptionPane.showMessageDialog(Desktop.desktop,
2584                                         "The selected region to create a tree may\nonly contain residues or gaps.\n" +
2585                                         "Try using the Pad function in the edit menu,\n" +
2586                                         "or one of the multiple sequence alignment web services.",
2587                                         "Sequences in selection are not aligned",
2588                                         JOptionPane.WARNING_MESSAGE);
2589
2590           return;
2591         }
2592       }
2593
2594       title = title + " on region";
2595       tp = new TreePanel(alignPanel, type, pwType);
2596     }
2597     else
2598     {
2599       //are the sequences aligned?
2600       if (!viewport.alignment.isAligned())
2601       {
2602         JOptionPane.showMessageDialog(Desktop.desktop,
2603                                       "The sequences must be aligned before creating a tree.\n" +
2604                                       "Try using the Pad function in the edit menu,\n" +
2605                                       "or one of the multiple sequence alignment web services.",
2606                                       "Sequences not aligned",
2607                                       JOptionPane.WARNING_MESSAGE);
2608
2609         return;
2610       }
2611
2612       if(viewport.alignment.getHeight()<2)
2613         return;
2614
2615       tp = new TreePanel(alignPanel, type, pwType);
2616     }
2617
2618     addTreeMenuItem(tp, title);
2619
2620     Desktop.addInternalFrame(tp, title + " from " + this.title, 600, 500);
2621   }
2622
2623   /**
2624    * DOCUMENT ME!
2625    *
2626    * @param title DOCUMENT ME!
2627    * @param order DOCUMENT ME!
2628    */
2629   public void addSortByOrderMenuItem(String title, final AlignmentOrder order)
2630   {
2631     final JMenuItem item = new JMenuItem("by " + title);
2632     sort.add(item);
2633     item.addActionListener(new java.awt.event.ActionListener()
2634     {
2635       public void actionPerformed(ActionEvent e)
2636       {
2637         SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2638
2639         // TODO: JBPNote - have to map order entries to curent SequenceI pointers
2640         AlignmentSorter.sortBy(viewport.getAlignment(), order);
2641
2642         addHistoryItem(new OrderCommand(order.getName(), oldOrder, viewport.alignment));
2643
2644         alignPanel.repaint();
2645       }
2646     });
2647   }
2648
2649   /**
2650    * Maintain the Order by->Displayed Tree menu.
2651    * Creates a new menu item for a TreePanel with an appropriate
2652    * <code>jalview.analysis.AlignmentSorter</code> call. Listeners are added
2653    * to remove the menu item when the treePanel is closed, and adjust
2654    * the tree leaf to sequence mapping when the alignment is modified.
2655    * @param treePanel Displayed tree window.
2656    * @param title SortBy menu item title.
2657    */
2658   void addTreeMenuItem(final TreePanel treePanel, String title)
2659   {
2660     final JMenuItem item = new JMenuItem(title);
2661
2662     treeCount++;
2663
2664     if (treeCount == 1)
2665     {
2666       sort.add(sortByTreeMenu);
2667     }
2668
2669     sortByTreeMenu.add(item);
2670     item.addActionListener(new java.awt.event.ActionListener()
2671     {
2672       public void actionPerformed(ActionEvent e)
2673       {
2674         SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2675         AlignmentSorter.sortByTree(viewport.getAlignment(),
2676                                    treePanel.getTree());
2677
2678         addHistoryItem(new OrderCommand("Tree Sort",
2679                                         oldOrder,
2680                                         viewport.alignment));
2681
2682
2683         alignPanel.repaint();
2684       }
2685     });
2686
2687     treePanel.addInternalFrameListener(new javax.swing.event.
2688                                        InternalFrameAdapter()
2689     {
2690       public void internalFrameClosed(
2691           javax.swing.event.InternalFrameEvent evt)
2692       {
2693         treeCount--;
2694         sortByTreeMenu.remove(item);
2695
2696         if (treeCount == 0)
2697         {
2698           sort.remove(sortByTreeMenu);
2699         }
2700       }
2701       ;
2702     });
2703   }
2704
2705   /**
2706    * Work out whether the whole set of sequences
2707    * or just the selected set will be submitted for multiple alignment.
2708    *
2709    */
2710   private jalview.datamodel.AlignmentView gatherSequencesForAlignment()
2711   {
2712     // Now, check we have enough sequences
2713     AlignmentView msa = null;
2714
2715     if ( (viewport.getSelectionGroup() != null) &&
2716         (viewport.getSelectionGroup().getSize(false) > 1))
2717     {
2718       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
2719       /*SequenceGroup seqs = viewport.getSelectionGroup();
2720       int sz;
2721       msa = new SequenceI[sz = seqs.getSize(false)];
2722
2723       for (int i = 0; i < sz; i++)
2724       {
2725         msa[i] = (SequenceI) seqs.getSequenceAt(i);
2726       } */
2727       msa = viewport.getAlignmentView(true);
2728     }
2729     else
2730     {
2731       /*Vector seqs = viewport.getAlignment().getSequences();
2732
2733       if (seqs.size() > 1)
2734       {
2735         msa = new SequenceI[seqs.size()];
2736
2737         for (int i = 0; i < seqs.size(); i++)
2738         {
2739           msa[i] = (SequenceI) seqs.elementAt(i);
2740         }
2741       }*/
2742       msa = viewport.getAlignmentView(false);
2743     }
2744     return msa;
2745   }
2746
2747   /**
2748    * Decides what is submitted to a secondary structure prediction service,
2749    * the currently selected sequence, or the currently selected alignment
2750    * (where the first sequence in the set is the one that the prediction
2751    * will be for).
2752    */
2753   AlignmentView gatherSeqOrMsaForSecStrPrediction()
2754   {
2755    AlignmentView seqs = null;
2756
2757     if ( (viewport.getSelectionGroup() != null) &&
2758         (viewport.getSelectionGroup().getSize(false) > 0))
2759     {
2760       seqs = viewport.getAlignmentView(true);
2761     }
2762     else
2763     {
2764       seqs = viewport.getAlignmentView(false);
2765     }
2766     // limit sequences - JBPNote in future - could spawn multiple prediction jobs
2767     // TODO: viewport.alignment.isAligned is a global state - the local selection may well be aligned - we preserve 2.0.8 behaviour for moment.
2768     if (!viewport.alignment.isAligned())
2769     {
2770       seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] } );
2771     }
2772     return seqs;
2773   }
2774   /**
2775    * DOCUMENT ME!
2776    *
2777    * @param e DOCUMENT ME!
2778    */
2779   protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)
2780   {
2781     // Pick the tree file
2782     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2783         getProperty(
2784             "LAST_DIRECTORY"));
2785     chooser.setFileView(new JalviewFileView());
2786     chooser.setDialogTitle("Select a newick-like tree file");
2787     chooser.setToolTipText("Load a tree file");
2788
2789     int value = chooser.showOpenDialog(null);
2790
2791     if (value == JalviewFileChooser.APPROVE_OPTION)
2792     {
2793       String choice = chooser.getSelectedFile().getPath();
2794       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
2795
2796       try
2797       {
2798         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,
2799             "File");
2800         viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
2801       }
2802       catch (Exception ex)
2803       {
2804         JOptionPane.showMessageDialog(Desktop.desktop,
2805                                       "Problem reading tree file",
2806                                       ex.getMessage(),
2807                                       JOptionPane.WARNING_MESSAGE);
2808         ex.printStackTrace();
2809       }
2810     }
2811   }
2812
2813
2814   public TreePanel ShowNewickTree(NewickFile nf, String title)
2815   {
2816     return ShowNewickTree(nf,title,600,500,4,5);
2817   }
2818   public TreePanel ShowNewickTree(NewickFile nf, String title, AlignmentView input)
2819   {
2820     return ShowNewickTree(nf,title, input, 600,500,4,5);
2821   }
2822   public TreePanel ShowNewickTree(NewickFile nf, String title, int w,int h,int x, int y) {
2823     return ShowNewickTree(nf, title, null, w, h, x, y);
2824   }
2825   /**
2826    * Add a treeviewer for the tree extracted from a newick file object to the current alignment view
2827    *
2828    * @param nf the tree
2829    * @param title tree viewer title
2830    * @param input Associated alignment input data (or null)
2831    * @param w width
2832    * @param h height
2833    * @param x position
2834    * @param y position
2835    * @return TreePanel handle
2836    */
2837   public TreePanel ShowNewickTree(NewickFile nf, String title, AlignmentView input, int w,int h,int x, int y) {
2838     TreePanel tp = null;
2839
2840     try
2841     {
2842       nf.parse();
2843
2844       if (nf.getTree() != null)
2845       {
2846         tp = new TreePanel(alignPanel,
2847                            "FromFile",
2848                            title,
2849                            nf, input);
2850
2851         tp.setSize(w,h);
2852
2853         if(x>0 && y>0)
2854           tp.setLocation(x,y);
2855
2856
2857         Desktop.addInternalFrame(tp, title, w, h);
2858         addTreeMenuItem(tp, title);
2859       }
2860     }
2861     catch (Exception ex)
2862     {
2863       ex.printStackTrace();
2864     }
2865
2866     return tp;
2867   }
2868
2869   class PrintThread
2870       extends Thread
2871   {
2872     public void run()
2873     {
2874       PrinterJob printJob = PrinterJob.getPrinterJob();
2875       PageFormat pf = printJob.pageDialog(printJob.defaultPage());
2876       printJob.setPrintable(alignPanel, pf);
2877
2878       if (printJob.printDialog())
2879       {
2880         try
2881         {
2882           printJob.print();
2883         }
2884         catch (Exception PrintException)
2885         {
2886           PrintException.printStackTrace();
2887         }
2888       }
2889     }
2890   }
2891
2892   /**
2893    * Generates menu items and listener event actions for web service clients
2894    *
2895    */
2896   public void BuildWebServiceMenu()
2897   {
2898     if ( (Discoverer.services != null)
2899         && (Discoverer.services.size() > 0))
2900     {
2901       Vector msaws = (Vector) Discoverer.services.get("MsaWS");
2902       Vector secstrpr = (Vector) Discoverer.services.get("SecStrPred");
2903       Vector wsmenu = new Vector();
2904       final AlignFrame af = this;
2905       if (msaws != null)
2906       {
2907         // Add any Multiple Sequence Alignment Services
2908         final JMenu msawsmenu = new JMenu("Alignment");
2909         for (int i = 0, j = msaws.size(); i < j; i++)
2910         {
2911           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.
2912               get(i);
2913           final JMenuItem method = new JMenuItem(sh.getName());
2914           method.addActionListener(new ActionListener()
2915           {
2916             public void actionPerformed(ActionEvent e)
2917             {
2918               AlignmentView msa = gatherSequencesForAlignment();
2919               new jalview.ws.MsaWSClient(sh, title, msa,
2920                   false, true, viewport.getAlignment().getDataset(), af);
2921
2922             }
2923
2924           });
2925           msawsmenu.add(method);
2926           // Deal with services that we know accept partial alignments.
2927           if (sh.getName().indexOf("lustal") > -1)
2928           {
2929             // We know that ClustalWS can accept partial alignments for refinement.
2930             final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");
2931             methodR.addActionListener(new ActionListener()
2932             {
2933               public void actionPerformed(ActionEvent e)
2934               {
2935                 AlignmentView msa = gatherSequencesForAlignment();
2936                 new jalview.ws.MsaWSClient(sh, title, msa,
2937                     true, true, viewport.getAlignment().getDataset(), af);
2938
2939               }
2940
2941             });
2942             msawsmenu.add(methodR);
2943
2944           }
2945         }
2946         wsmenu.add(msawsmenu);
2947       }
2948       if (secstrpr != null)
2949       {
2950         // Add any secondary structure prediction services
2951         final JMenu secstrmenu = new JMenu("Secondary Structure Prediction");
2952         for (int i = 0, j = secstrpr.size(); i < j; i++)
2953         {
2954           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)
2955               secstrpr.get(i);
2956           final JMenuItem method = new JMenuItem(sh.getName());
2957           method.addActionListener(new ActionListener()
2958           {
2959             public void actionPerformed(ActionEvent e)
2960             {
2961               AlignmentView msa = gatherSeqOrMsaForSecStrPrediction();
2962               if (msa.getSequences().length == 1)
2963               {
2964                 // Single Sequence prediction
2965                 new jalview.ws.JPredClient(sh, title, false, msa, af, true);
2966               }
2967               else
2968               {
2969                 if (msa.getSequences().length > 1)
2970                 {
2971                   // Sequence profile based prediction
2972                   new jalview.ws.JPredClient(sh,
2973                       title, true, msa, af, true);
2974                 }
2975               }
2976             }
2977           });
2978           secstrmenu.add(method);
2979         }
2980         wsmenu.add(secstrmenu);
2981       }
2982       this.webService.removeAll();
2983       for (int i = 0, j = wsmenu.size(); i < j; i++)
2984       {
2985         webService.add( (JMenu) wsmenu.get(i));
2986       }
2987     }
2988     else
2989     {
2990       this.webService.removeAll();
2991       this.webService.add(this.webServiceNoServices);
2992     }
2993     // TODO: add in rediscovery function
2994     // TODO: reduce code redundancy.
2995     // TODO: group services by location as well as function.
2996   }
2997
2998  /* public void vamsasStore_actionPerformed(ActionEvent e)
2999   {
3000     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
3001         getProperty("LAST_DIRECTORY"));
3002
3003     chooser.setFileView(new JalviewFileView());
3004     chooser.setDialogTitle("Export to Vamsas file");
3005     chooser.setToolTipText("Export");
3006
3007     int value = chooser.showSaveDialog(this);
3008
3009     if (value == JalviewFileChooser.APPROVE_OPTION)
3010     {
3011       jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);
3012       //vs.store(chooser.getSelectedFile().getAbsolutePath()   );
3013       vs.storeJalview( chooser.getSelectedFile().getAbsolutePath(), this);
3014     }
3015   }*/
3016
3017
3018
3019
3020 public void showTranslation_actionPerformed(ActionEvent e)
3021 {
3022   SequenceI [] selection = viewport.getSelectionAsNewSequence();
3023   String [] seqstring = viewport.getViewAsString(true);
3024
3025   int s, sSize = selection.length;
3026   SequenceI [] newSeq = new SequenceI[sSize];
3027
3028   int res, resSize;
3029   StringBuffer protein;
3030   String seq;
3031   for(s=0; s<sSize; s++)
3032   {
3033     protein = new StringBuffer();
3034     seq = AlignSeq.extractGaps("-. ", seqstring[s]);
3035     resSize = seq.length();
3036     resSize -= resSize%3;
3037
3038     for(res = 0; res < resSize; res+=3)
3039     {
3040       String codon = seq.substring(res, res+3);
3041       codon = codon.replace('U', 'T');
3042       String aa = ResidueProperties.codonTranslate(codon);
3043       if(aa==null)
3044         protein.append(viewport.getGapCharacter());
3045       else if(aa.equals("STOP"))
3046         protein.append("X");
3047       else
3048         protein.append( aa );
3049     }
3050     newSeq[s] = new Sequence(selection[s].getName(),
3051                              protein.toString());
3052   }
3053
3054
3055   AlignmentI al = new Alignment(newSeq);
3056   al.setDataset(null);
3057
3058
3059   ////////////////////////////////
3060   // Copy annotations across
3061   jalview.datamodel.AlignmentAnnotation[] annotations
3062       = viewport.alignment.getAlignmentAnnotation();
3063   int a, aSize;
3064   if(annotations!=null)
3065   {
3066     for (int i = 0; i < annotations.length; i++)
3067     {
3068       if (annotations[i].label.equals("Quality") ||
3069           annotations[i].label.equals("Conservation") ||
3070           annotations[i].label.equals("Consensus"))
3071       {
3072         continue;
3073       }
3074
3075       aSize = viewport.alignment.getWidth() / 3;
3076       jalview.datamodel.Annotation[] anots =
3077           new jalview.datamodel.Annotation[aSize];
3078
3079       for (a = 0; a < viewport.alignment.getWidth(); a++)
3080       {
3081         if (annotations[i].annotations[a] == null
3082             || annotations[i].annotations[a] == null)
3083           continue;
3084
3085         anots[a / 3] = new Annotation(
3086             annotations[i].annotations[a].displayCharacter,
3087             annotations[i].annotations[a].description,
3088             annotations[i].annotations[a].secondaryStructure,
3089             annotations[i].annotations[a].value,
3090             annotations[i].annotations[a].colour);
3091       }
3092
3093       jalview.datamodel.AlignmentAnnotation aa
3094           = new jalview.datamodel.AlignmentAnnotation(annotations[i].label,
3095           annotations[i].description, anots);
3096       al.addAnnotation(aa);
3097     }
3098   }
3099
3100     AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
3101     Desktop.addInternalFrame(af, "Translation of "+this.getTitle(),
3102                              DEFAULT_WIDTH,
3103                              DEFAULT_HEIGHT);
3104
3105
3106
3107
3108 }
3109
3110 /**
3111  * DOCUMENT ME!
3112  *
3113  * @param String DOCUMENT ME!
3114  */
3115 public boolean parseFeaturesFile(String file, String type)
3116 {
3117     boolean featuresFile = false;
3118     try{
3119       featuresFile = new FeaturesFile(file, type).parse(viewport.alignment.getDataset(),
3120                                          alignPanel.seqPanel.seqCanvas.
3121                                          getFeatureRenderer().featureColours,
3122                                          false);
3123     }
3124     catch(Exception ex)
3125     {
3126       ex.printStackTrace();
3127     }
3128
3129     if(featuresFile)
3130     {
3131       viewport.showSequenceFeatures = true;
3132       showSeqFeatures.setSelected(true);
3133       alignPanel.repaint();
3134     }
3135
3136     return featuresFile;
3137 }
3138
3139 public void dragEnter(DropTargetDragEvent evt)
3140 {}
3141
3142 public void dragExit(DropTargetEvent evt)
3143 {}
3144
3145 public void dragOver(DropTargetDragEvent evt)
3146 {}
3147
3148 public void dropActionChanged(DropTargetDragEvent evt)
3149 {}
3150
3151 public void drop(DropTargetDropEvent evt)
3152 {
3153     Transferable t = evt.getTransferable();
3154     java.util.List files = null;
3155
3156     try
3157     {
3158       DataFlavor uriListFlavor = new DataFlavor("text/uri-list;class=java.lang.String");
3159       if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3160       {
3161         //Works on Windows and MacOSX
3162         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3163         files = (java.util.List) t.getTransferData(DataFlavor.javaFileListFlavor);
3164       }
3165       else if (t.isDataFlavorSupported(uriListFlavor))
3166       {
3167         // This is used by Unix drag system
3168         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3169         String data = (String) t.getTransferData(uriListFlavor);
3170         files = new java.util.ArrayList(1);
3171         for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3172             data,
3173             "\r\n");
3174              st.hasMoreTokens(); )
3175         {
3176           String s = st.nextToken();
3177           if (s.startsWith("#"))
3178           {
3179             // the line is a comment (as per the RFC 2483)
3180             continue;
3181           }
3182
3183           java.net.URI uri = new java.net.URI(s);
3184           java.io.File file = new java.io.File(uri);
3185           files.add(file);
3186         }
3187       }
3188     }
3189     catch (Exception e)
3190     {
3191       e.printStackTrace();
3192     }
3193     if (files != null)
3194     {
3195       try
3196       {
3197
3198         for (int i = 0; i < files.size(); i++)
3199         {
3200           loadJalviewDataFile(files.get(i).toString());
3201         }
3202       }
3203       catch (Exception ex)
3204       {
3205         ex.printStackTrace();
3206       }
3207     }
3208 }
3209
3210   // This method will attempt to load a "dropped" file first by testing
3211   // whether its and Annotation file, then features file. If both are
3212   // false then the user may have dropped an alignment file onto this
3213   // AlignFrame
3214    public void loadJalviewDataFile(String file)
3215   {
3216     try{
3217       String protocol = "File";
3218
3219       if (file.indexOf("http:") > -1 || file.indexOf("file:") > -1)
3220       {
3221         protocol = "URL";
3222       }
3223
3224       boolean isAnnotation = new AnnotationFile().readAnnotationFile(viewport.
3225           alignment, file);
3226
3227       if (!isAnnotation)
3228       {
3229         boolean isGroupsFile = parseFeaturesFile(file,protocol);
3230         if (!isGroupsFile)
3231         {
3232           String format = new IdentifyFile().Identify(file, protocol);
3233
3234           if(format.equalsIgnoreCase("JnetFile"))
3235           {
3236             jalview.io.JPredFile predictions = new jalview.io.JPredFile(
3237                 file, protocol);
3238             new JnetAnnotationMaker().add_annotation(predictions,
3239                 viewport.getAlignment(),
3240                 0, false);
3241             alignPanel.adjustAnnotationHeight();
3242             alignPanel.repaint();
3243           }
3244           else
3245             new FileLoader().LoadFile(viewport, file, protocol, format);
3246         }
3247       }
3248       else
3249       {
3250         // (isAnnotation)
3251         alignPanel.adjustAnnotationHeight();
3252       }
3253
3254     }catch(Exception ex)
3255     {
3256       ex.printStackTrace();
3257     }
3258   }
3259
3260   public void tabSelectionChanged(int index)
3261   {
3262     if (index > -1)
3263     {
3264       alignPanel = (AlignmentPanel) alignPanels.elementAt(index);
3265       viewport = alignPanel.av;
3266       setMenusFromViewport(viewport);
3267     }
3268   }
3269
3270   public void tabbedPane_mousePressed(MouseEvent e)
3271   {
3272     if(SwingUtilities.isRightMouseButton(e))
3273     {
3274       String reply = JOptionPane.showInternalInputDialog(this,
3275           "Enter View Name",
3276           "Edit View Name",
3277           JOptionPane.QUESTION_MESSAGE);
3278
3279       if (reply != null)
3280       {
3281         viewport.viewName = reply;
3282         tabbedPane.setTitleAt( tabbedPane.getSelectedIndex() ,reply);
3283       }
3284     }
3285   }
3286
3287
3288   public AlignViewport getCurrentView()
3289   {
3290     return viewport;
3291   }
3292 }