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