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