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