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