Sequence colour in viewport
[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       viewport.gatherViewsHere = true;
1699     }
1700     tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
1701   }
1702
1703
1704   /**
1705    * DOCUMENT ME!
1706    *
1707    * @param e DOCUMENT ME!
1708    */
1709   public void font_actionPerformed(ActionEvent e)
1710   {
1711     new FontChooser(alignPanel);
1712   }
1713
1714
1715   /**
1716    * DOCUMENT ME!
1717    *
1718    * @param e DOCUMENT ME!
1719    */
1720   protected void seqLimit_actionPerformed(ActionEvent e)
1721   {
1722     viewport.setShowJVSuffix(seqLimits.isSelected());
1723
1724     alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel.calculateIdWidth());
1725     alignPanel.repaint();
1726   }
1727
1728
1729   /**
1730    * DOCUMENT ME!
1731    *
1732    * @param e DOCUMENT ME!
1733    */
1734   protected void colourTextMenuItem_actionPerformed(ActionEvent e)
1735   {
1736     viewport.setColourText(colourTextMenuItem.isSelected());
1737     alignPanel.repaint();
1738   }
1739
1740   /**
1741    * DOCUMENT ME!
1742    *
1743    * @param e DOCUMENT ME!
1744    */
1745   public void wrapMenuItem_actionPerformed(ActionEvent e)
1746   {
1747     scaleAbove.setVisible(wrapMenuItem.isSelected());
1748     scaleLeft.setVisible(wrapMenuItem.isSelected());
1749     scaleRight.setVisible(wrapMenuItem.isSelected());
1750     viewport.setWrapAlignment(wrapMenuItem.isSelected());
1751     alignPanel.setWrapAlignment(wrapMenuItem.isSelected());
1752   }
1753
1754   public void showAllSeqs_actionPerformed(ActionEvent e)
1755   {
1756     viewport.showAllHiddenSeqs();
1757   }
1758
1759   public void showAllColumns_actionPerformed(ActionEvent e)
1760   {
1761     viewport.showAllHiddenColumns();
1762     repaint();
1763   }
1764
1765   public void hideSelSequences_actionPerformed(ActionEvent e)
1766   {
1767     viewport.hideAllSelectedSeqs();
1768     alignPanel.repaint();
1769   }
1770
1771   public void hideSelColumns_actionPerformed(ActionEvent e)
1772   {
1773     viewport.hideSelectedColumns();
1774     alignPanel.repaint();
1775   }
1776
1777   public void hiddenMarkers_actionPerformed(ActionEvent e)
1778   {
1779     viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
1780     repaint();
1781   }
1782
1783   /**
1784    * DOCUMENT ME!
1785    *
1786    * @param e DOCUMENT ME!
1787    */
1788   protected void scaleAbove_actionPerformed(ActionEvent e)
1789   {
1790     viewport.setScaleAboveWrapped(scaleAbove.isSelected());
1791     alignPanel.repaint();
1792   }
1793
1794   /**
1795    * DOCUMENT ME!
1796    *
1797    * @param e DOCUMENT ME!
1798    */
1799   protected void scaleLeft_actionPerformed(ActionEvent e)
1800   {
1801     viewport.setScaleLeftWrapped(scaleLeft.isSelected());
1802     alignPanel.repaint();
1803   }
1804
1805   /**
1806    * DOCUMENT ME!
1807    *
1808    * @param e DOCUMENT ME!
1809    */
1810   protected void scaleRight_actionPerformed(ActionEvent e)
1811   {
1812     viewport.setScaleRightWrapped(scaleRight.isSelected());
1813     alignPanel.repaint();
1814   }
1815
1816   /**
1817    * DOCUMENT ME!
1818    *
1819    * @param e DOCUMENT ME!
1820    */
1821   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
1822   {
1823     viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
1824     alignPanel.repaint();
1825   }
1826
1827   /**
1828    * DOCUMENT ME!
1829    *
1830    * @param e DOCUMENT ME!
1831    */
1832   public void viewTextMenuItem_actionPerformed(ActionEvent e)
1833   {
1834     viewport.setShowText(viewTextMenuItem.isSelected());
1835     alignPanel.repaint();
1836   }
1837
1838   /**
1839    * DOCUMENT ME!
1840    *
1841    * @param e DOCUMENT ME!
1842    */
1843   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
1844   {
1845     viewport.setRenderGaps(renderGapsMenuItem.isSelected());
1846     alignPanel.repaint();
1847   }
1848
1849
1850   public FeatureSettings featureSettings;
1851   public void featureSettings_actionPerformed(ActionEvent e)
1852   {
1853     if(featureSettings !=null )
1854     {
1855       featureSettings.close();
1856       featureSettings = null;
1857     }
1858     featureSettings = new FeatureSettings(this);
1859   }
1860
1861   /**
1862    * DOCUMENT ME!
1863    *
1864    * @param evt DOCUMENT ME!
1865    */
1866   public void showSeqFeatures_actionPerformed(ActionEvent evt)
1867   {
1868     viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
1869     alignPanel.repaint();
1870     if (alignPanel.getOverviewPanel() != null)
1871     {
1872       alignPanel.getOverviewPanel().updateOverviewImage();
1873     }
1874   }
1875
1876   /**
1877    * DOCUMENT ME!
1878    *
1879    * @param e DOCUMENT ME!
1880    */
1881   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
1882   {
1883     viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());
1884     alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());
1885   }
1886
1887   /**
1888    * DOCUMENT ME!
1889    *
1890    * @param e DOCUMENT ME!
1891    */
1892   public void overviewMenuItem_actionPerformed(ActionEvent e)
1893   {
1894     if (alignPanel.overviewPanel != null)
1895     {
1896       return;
1897     }
1898
1899     JInternalFrame frame = new JInternalFrame();
1900     OverviewPanel overview = new OverviewPanel(alignPanel);
1901     frame.setContentPane(overview);
1902     Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),
1903                              frame.getWidth(), frame.getHeight());
1904     frame.pack();
1905     frame.setLayer(JLayeredPane.PALETTE_LAYER);
1906     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
1907     {
1908       public void internalFrameClosed(
1909           javax.swing.event.InternalFrameEvent evt)
1910       {
1911         alignPanel.setOverviewPanel(null);
1912       }
1913       ;
1914     });
1915
1916     alignPanel.setOverviewPanel(overview);
1917   }
1918
1919   /**
1920    * DOCUMENT ME!
1921    *
1922    * @param e DOCUMENT ME!
1923    */
1924   protected void noColourmenuItem_actionPerformed(ActionEvent e)
1925   {
1926     changeColour(null);
1927   }
1928
1929   /**
1930    * DOCUMENT ME!
1931    *
1932    * @param e DOCUMENT ME!
1933    */
1934   public void clustalColour_actionPerformed(ActionEvent e)
1935   {
1936     changeColour(new ClustalxColourScheme(
1937         viewport.alignment.getSequences(), viewport.alignment.getWidth()));
1938   }
1939
1940   /**
1941    * DOCUMENT ME!
1942    *
1943    * @param e DOCUMENT ME!
1944    */
1945   public void zappoColour_actionPerformed(ActionEvent e)
1946   {
1947     changeColour(new ZappoColourScheme());
1948   }
1949
1950   /**
1951    * DOCUMENT ME!
1952    *
1953    * @param e DOCUMENT ME!
1954    */
1955   public void taylorColour_actionPerformed(ActionEvent e)
1956   {
1957     changeColour(new TaylorColourScheme());
1958   }
1959
1960   /**
1961    * DOCUMENT ME!
1962    *
1963    * @param e DOCUMENT ME!
1964    */
1965   public void hydrophobicityColour_actionPerformed(ActionEvent e)
1966   {
1967     changeColour(new HydrophobicColourScheme());
1968   }
1969
1970   /**
1971    * DOCUMENT ME!
1972    *
1973    * @param e DOCUMENT ME!
1974    */
1975   public void helixColour_actionPerformed(ActionEvent e)
1976   {
1977     changeColour(new HelixColourScheme());
1978   }
1979
1980   /**
1981    * DOCUMENT ME!
1982    *
1983    * @param e DOCUMENT ME!
1984    */
1985   public void strandColour_actionPerformed(ActionEvent e)
1986   {
1987     changeColour(new StrandColourScheme());
1988   }
1989
1990   /**
1991    * DOCUMENT ME!
1992    *
1993    * @param e DOCUMENT ME!
1994    */
1995   public void turnColour_actionPerformed(ActionEvent e)
1996   {
1997     changeColour(new TurnColourScheme());
1998   }
1999
2000   /**
2001    * DOCUMENT ME!
2002    *
2003    * @param e DOCUMENT ME!
2004    */
2005   public void buriedColour_actionPerformed(ActionEvent e)
2006   {
2007     changeColour(new BuriedColourScheme());
2008   }
2009
2010   /**
2011    * DOCUMENT ME!
2012    *
2013    * @param e DOCUMENT ME!
2014    */
2015   public void nucleotideColour_actionPerformed(ActionEvent e)
2016   {
2017     changeColour(new NucleotideColourScheme());
2018   }
2019
2020   public void annotationColour_actionPerformed(ActionEvent e)
2021   {
2022     new AnnotationColourChooser(viewport, alignPanel);
2023   }
2024
2025
2026   /**
2027    * DOCUMENT ME!
2028    *
2029    * @param e DOCUMENT ME!
2030    */
2031   protected void applyToAllGroups_actionPerformed(ActionEvent e)
2032   {
2033     viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
2034   }
2035
2036   /**
2037    * DOCUMENT ME!
2038    *
2039    * @param cs DOCUMENT ME!
2040    */
2041   public void changeColour(ColourSchemeI cs)
2042   {
2043     int threshold = 0;
2044
2045     if(cs!=null)
2046     {
2047       if (viewport.getAbovePIDThreshold())
2048       {
2049         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,
2050                                                    "Background");
2051
2052         cs.setThreshold(threshold,
2053                         viewport.getIgnoreGapsConsensus());
2054
2055         viewport.setGlobalColourScheme(cs);
2056       }
2057       else
2058       {
2059         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2060       }
2061
2062       if (viewport.getConservationSelected())
2063       {
2064
2065         Alignment al = (Alignment) viewport.alignment;
2066         Conservation c = new Conservation("All",
2067                                           ResidueProperties.propHash, 3,
2068                                           al.getSequences(), 0,
2069                                           al.getWidth() - 1);
2070
2071         c.calculate();
2072         c.verdict(false, viewport.ConsPercGaps);
2073
2074         cs.setConservation(c);
2075
2076         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,
2077             "Background"));
2078       }
2079       else
2080       {
2081         cs.setConservation(null);
2082       }
2083
2084       cs.setConsensus(viewport.hconsensus);
2085     }
2086
2087     viewport.setGlobalColourScheme(cs);
2088
2089     if (viewport.getColourAppliesToAllGroups())
2090     {
2091       Vector groups = viewport.alignment.getGroups();
2092
2093       for (int i = 0; i < groups.size(); i++)
2094       {
2095         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
2096
2097         if (cs == null)
2098         {
2099           sg.cs = null;
2100           continue;
2101         }
2102
2103         if (cs instanceof ClustalxColourScheme)
2104         {
2105           sg.cs = new ClustalxColourScheme(
2106               sg.getSequences(true), sg.getWidth());
2107         }
2108         else if (cs instanceof UserColourScheme)
2109         {
2110           sg.cs = new UserColourScheme( ( (UserColourScheme) cs).getColours());
2111         }
2112         else
2113         {
2114           try
2115           {
2116             sg.cs = (ColourSchemeI) cs.getClass().newInstance();
2117           }
2118           catch (Exception ex)
2119           {
2120           }
2121         }
2122
2123         if (viewport.getAbovePIDThreshold()
2124             || cs instanceof PIDColourScheme
2125             || cs instanceof Blosum62ColourScheme)
2126         {
2127          sg.cs.setThreshold(threshold,
2128                 viewport.getIgnoreGapsConsensus());
2129
2130          sg.cs.setConsensus(AAFrequency.calculate(
2131              sg.getSequences(true), sg.getStartRes(),
2132              sg.getEndRes()+1));
2133        }
2134         else
2135           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2136
2137
2138         if (viewport.getConservationSelected())
2139         {
2140           Conservation c = new Conservation("Group",
2141                                             ResidueProperties.propHash, 3,
2142                                             sg.getSequences(true),
2143                                             sg.getStartRes(),
2144                                             sg.getEndRes()+1);
2145           c.calculate();
2146           c.verdict(false, viewport.ConsPercGaps);
2147           sg.cs.setConservation(c);
2148         }
2149         else
2150           sg.cs.setConservation(null);
2151       }
2152     }
2153
2154     if (alignPanel.getOverviewPanel() != null)
2155     {
2156       alignPanel.getOverviewPanel().updateOverviewImage();
2157     }
2158
2159     alignPanel.repaint();
2160   }
2161
2162   /**
2163    * DOCUMENT ME!
2164    *
2165    * @param e DOCUMENT ME!
2166    */
2167   protected void modifyPID_actionPerformed(ActionEvent e)
2168   {
2169     if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme!=null)
2170     {
2171       SliderPanel.setPIDSliderSource(alignPanel,
2172                                      viewport.getGlobalColourScheme(),
2173                                      "Background");
2174       SliderPanel.showPIDSlider();
2175     }
2176   }
2177
2178   /**
2179    * DOCUMENT ME!
2180    *
2181    * @param e DOCUMENT ME!
2182    */
2183   protected void modifyConservation_actionPerformed(ActionEvent e)
2184   {
2185     if (viewport.getConservationSelected() && viewport.globalColourScheme!=null)
2186     {
2187       SliderPanel.setConservationSlider(alignPanel,
2188                                         viewport.globalColourScheme,
2189                                         "Background");
2190       SliderPanel.showConservationSlider();
2191     }
2192   }
2193
2194   /**
2195    * DOCUMENT ME!
2196    *
2197    * @param e DOCUMENT ME!
2198    */
2199   protected void conservationMenuItem_actionPerformed(ActionEvent e)
2200   {
2201     viewport.setConservationSelected(conservationMenuItem.isSelected());
2202
2203     viewport.setAbovePIDThreshold(false);
2204     abovePIDThreshold.setSelected(false);
2205
2206     changeColour(viewport.getGlobalColourScheme());
2207
2208     modifyConservation_actionPerformed(null);
2209   }
2210
2211   /**
2212    * DOCUMENT ME!
2213    *
2214    * @param e DOCUMENT ME!
2215    */
2216   public void abovePIDThreshold_actionPerformed(ActionEvent e)
2217   {
2218     viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());
2219
2220     conservationMenuItem.setSelected(false);
2221     viewport.setConservationSelected(false);
2222
2223     changeColour(viewport.getGlobalColourScheme());
2224
2225     modifyPID_actionPerformed(null);
2226   }
2227
2228   /**
2229    * DOCUMENT ME!
2230    *
2231    * @param e DOCUMENT ME!
2232    */
2233   public void userDefinedColour_actionPerformed(ActionEvent e)
2234   {
2235     if (e.getActionCommand().equals("User Defined..."))
2236     {
2237       new UserDefinedColours(alignPanel, null);
2238     }
2239     else
2240     {
2241       UserColourScheme udc = (UserColourScheme) UserDefinedColours.
2242           getUserColourSchemes().get(e.getActionCommand());
2243
2244       changeColour(udc);
2245     }
2246   }
2247
2248   public void updateUserColourMenu()
2249   {
2250
2251     Component[] menuItems = colourMenu.getMenuComponents();
2252     int i, iSize = menuItems.length;
2253     for (i = 0; i < iSize; i++)
2254     {
2255       if (menuItems[i].getName() != null &&
2256           menuItems[i].getName().equals("USER_DEFINED"))
2257       {
2258         colourMenu.remove(menuItems[i]);
2259         iSize--;
2260       }
2261     }
2262     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
2263     {
2264       java.util.Enumeration userColours = jalview.gui.UserDefinedColours.
2265           getUserColourSchemes().keys();
2266
2267       while (userColours.hasMoreElements())
2268       {
2269         final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(userColours.
2270             nextElement().toString());
2271         radioItem.setName("USER_DEFINED");
2272         radioItem.addMouseListener(new MouseAdapter()
2273             {
2274               public void mousePressed(MouseEvent evt)
2275               {
2276                 if(evt.isControlDown() || SwingUtilities.isRightMouseButton(evt))
2277                 {
2278                   radioItem.removeActionListener(radioItem.getActionListeners()[0]);
2279
2280                   int option = JOptionPane.showInternalConfirmDialog(jalview.gui.Desktop.desktop,
2281                       "Remove from default list?",
2282                       "Remove user defined colour",
2283                       JOptionPane.YES_NO_OPTION);
2284                   if(option == JOptionPane.YES_OPTION)
2285                   {
2286                     jalview.gui.UserDefinedColours.removeColourFromDefaults(radioItem.getText());
2287                     colourMenu.remove(radioItem);
2288                   }
2289                   else
2290                     radioItem.addActionListener(new ActionListener()
2291                     {
2292                       public void actionPerformed(ActionEvent evt)
2293                       {
2294                         userDefinedColour_actionPerformed(evt);
2295                       }
2296                     });
2297                 }
2298               }
2299             });
2300         radioItem.addActionListener(new ActionListener()
2301         {
2302           public void actionPerformed(ActionEvent evt)
2303           {
2304             userDefinedColour_actionPerformed(evt);
2305           }
2306         });
2307
2308         colourMenu.insert(radioItem, 15);
2309         colours.add(radioItem);
2310       }
2311     }
2312   }
2313
2314   /**
2315    * DOCUMENT ME!
2316    *
2317    * @param e DOCUMENT ME!
2318    */
2319   public void PIDColour_actionPerformed(ActionEvent e)
2320   {
2321     changeColour(new PIDColourScheme());
2322   }
2323
2324   /**
2325    * DOCUMENT ME!
2326    *
2327    * @param e DOCUMENT ME!
2328    */
2329   public void BLOSUM62Colour_actionPerformed(ActionEvent e)
2330   {
2331     changeColour(new Blosum62ColourScheme());
2332   }
2333
2334   /**
2335    * DOCUMENT ME!
2336    *
2337    * @param e DOCUMENT ME!
2338    */
2339   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
2340   {
2341     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2342     AlignmentSorter.sortByPID(viewport.getAlignment(),
2343                               viewport.getAlignment().getSequenceAt(0));
2344     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder, viewport.alignment));
2345     alignPanel.repaint();
2346   }
2347
2348   /**
2349    * DOCUMENT ME!
2350    *
2351    * @param e DOCUMENT ME!
2352    */
2353   public void sortIDMenuItem_actionPerformed(ActionEvent e)
2354   {
2355     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2356     AlignmentSorter.sortByID(viewport.getAlignment());
2357     addHistoryItem(new OrderCommand("ID Sort", oldOrder, viewport.alignment));
2358     alignPanel.repaint();
2359   }
2360
2361   /**
2362    * DOCUMENT ME!
2363    *
2364    * @param e DOCUMENT ME!
2365    */
2366   public void sortGroupMenuItem_actionPerformed(ActionEvent e)
2367   {
2368     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2369     AlignmentSorter.sortByGroup(viewport.getAlignment());
2370     addHistoryItem(new OrderCommand("Group Sort", oldOrder, viewport.alignment));
2371
2372     alignPanel.repaint();
2373   }
2374
2375   /**
2376    * DOCUMENT ME!
2377    *
2378    * @param e DOCUMENT ME!
2379    */
2380   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
2381   {
2382     new RedundancyPanel(alignPanel, this);
2383   }
2384
2385
2386   /**
2387    * DOCUMENT ME!
2388    *
2389    * @param e DOCUMENT ME!
2390    */
2391   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
2392   {
2393     if ( (viewport.getSelectionGroup() == null) ||
2394         (viewport.getSelectionGroup().getSize(false) < 2))
2395     {
2396       JOptionPane.showInternalMessageDialog(this,
2397                                             "You must select at least 2 sequences.",
2398                                             "Invalid Selection",
2399                                             JOptionPane.WARNING_MESSAGE);
2400     }
2401     else
2402     {
2403       JInternalFrame frame = new JInternalFrame();
2404       frame.setContentPane(new PairwiseAlignPanel(viewport));
2405       Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);
2406     }
2407   }
2408
2409   /**
2410    * DOCUMENT ME!
2411    *
2412    * @param e DOCUMENT ME!
2413    */
2414   public void PCAMenuItem_actionPerformed(ActionEvent e)
2415   {
2416     if ( ( (viewport.getSelectionGroup() != null) &&
2417           (viewport.getSelectionGroup().getSize(false) < 4) &&
2418           (viewport.getSelectionGroup().getSize(false) > 0)) ||
2419         (viewport.getAlignment().getHeight() < 4))
2420     {
2421       JOptionPane.showInternalMessageDialog(this,
2422                                             "Principal component analysis must take\n" +
2423                                             "at least 4 input sequences.",
2424                                             "Sequence selection insufficient",
2425                                             JOptionPane.WARNING_MESSAGE);
2426
2427       return;
2428     }
2429
2430      new PCAPanel(viewport);
2431   }
2432
2433
2434   public void autoCalculate_actionPerformed(ActionEvent e)
2435   {
2436     viewport.autoCalculateConsensus = autoCalculate.isSelected();
2437     if(viewport.autoCalculateConsensus)
2438     {
2439       viewport.firePropertyChange("alignment",
2440                                   null,
2441                                   viewport.getAlignment().getSequences());
2442     }
2443   }
2444
2445
2446   /**
2447    * DOCUMENT ME!
2448    *
2449    * @param e DOCUMENT ME!
2450    */
2451   public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
2452   {
2453     NewTreePanel("AV", "PID", "Average distance tree using PID");
2454   }
2455
2456   /**
2457    * DOCUMENT ME!
2458    *
2459    * @param e DOCUMENT ME!
2460    */
2461   public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
2462   {
2463     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
2464   }
2465
2466   /**
2467    * DOCUMENT ME!
2468    *
2469    * @param e DOCUMENT ME!
2470    */
2471   protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
2472   {
2473     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
2474   }
2475
2476   /**
2477    * DOCUMENT ME!
2478    *
2479    * @param e DOCUMENT ME!
2480    */
2481   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
2482   {
2483     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
2484   }
2485
2486   /**
2487    * DOCUMENT ME!
2488    *
2489    * @param type DOCUMENT ME!
2490    * @param pwType DOCUMENT ME!
2491    * @param title DOCUMENT ME!
2492    */
2493   void NewTreePanel(String type, String pwType, String title)
2494   {
2495     TreePanel tp;
2496
2497     if (viewport.getSelectionGroup() != null) {
2498       if (viewport.getSelectionGroup().getSize(false) < 3) {
2499         JOptionPane.showMessageDialog(Desktop.desktop,
2500                                       "You need to have more than two sequences selected to build a tree!",
2501                                       "Not enough sequences",
2502                                       JOptionPane.WARNING_MESSAGE);
2503         return;
2504       }
2505
2506       int s = 0;
2507       SequenceGroup sg = viewport.getSelectionGroup();
2508
2509       /* Decide if the selection is a column region */
2510       while (s < sg.getSize(false))
2511       {
2512         if ( ( (SequenceI) sg.getSequences(false).elementAt(s++)).getLength() <
2513             sg.getEndRes())
2514         {
2515           JOptionPane.showMessageDialog(Desktop.desktop,
2516                                         "The selected region to create a tree may\nonly contain residues or gaps.\n" +
2517                                         "Try using the Pad function in the edit menu,\n" +
2518                                         "or one of the multiple sequence alignment web services.",
2519                                         "Sequences in selection are not aligned",
2520                                         JOptionPane.WARNING_MESSAGE);
2521
2522           return;
2523         }
2524       }
2525
2526       title = title + " on region";
2527       tp = new TreePanel(alignPanel, type, pwType);
2528     }
2529     else
2530     {
2531       //are the sequences aligned?
2532       if (!viewport.alignment.isAligned())
2533       {
2534         JOptionPane.showMessageDialog(Desktop.desktop,
2535                                       "The sequences must be aligned before creating a tree.\n" +
2536                                       "Try using the Pad function in the edit menu,\n" +
2537                                       "or one of the multiple sequence alignment web services.",
2538                                       "Sequences not aligned",
2539                                       JOptionPane.WARNING_MESSAGE);
2540
2541         return;
2542       }
2543
2544       if(viewport.alignment.getHeight()<2)
2545         return;
2546
2547       tp = new TreePanel(alignPanel, type, pwType);
2548     }
2549
2550     addTreeMenuItem(tp, title);
2551
2552     Desktop.addInternalFrame(tp, title + " from " + this.title, 600, 500);
2553   }
2554
2555   /**
2556    * DOCUMENT ME!
2557    *
2558    * @param title DOCUMENT ME!
2559    * @param order DOCUMENT ME!
2560    */
2561   public void addSortByOrderMenuItem(String title, final AlignmentOrder order)
2562   {
2563     final JMenuItem item = new JMenuItem("by " + title);
2564     sort.add(item);
2565     item.addActionListener(new java.awt.event.ActionListener()
2566     {
2567       public void actionPerformed(ActionEvent e)
2568       {
2569         SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2570
2571         // TODO: JBPNote - have to map order entries to curent SequenceI pointers
2572         AlignmentSorter.sortBy(viewport.getAlignment(), order);
2573
2574         addHistoryItem(new OrderCommand(order.getName(), oldOrder, viewport.alignment));
2575
2576         alignPanel.repaint();
2577       }
2578     });
2579   }
2580
2581   /**
2582    * Maintain the Order by->Displayed Tree menu.
2583    * Creates a new menu item for a TreePanel with an appropriate
2584    * <code>jalview.analysis.AlignmentSorter</code> call. Listeners are added
2585    * to remove the menu item when the treePanel is closed, and adjust
2586    * the tree leaf to sequence mapping when the alignment is modified.
2587    * @param treePanel Displayed tree window.
2588    * @param title SortBy menu item title.
2589    */
2590   void addTreeMenuItem(final TreePanel treePanel, String title)
2591   {
2592     final JMenuItem item = new JMenuItem(title);
2593
2594     treeCount++;
2595
2596     if (treeCount == 1)
2597     {
2598       sort.add(sortByTreeMenu);
2599     }
2600
2601     sortByTreeMenu.add(item);
2602     item.addActionListener(new java.awt.event.ActionListener()
2603     {
2604       public void actionPerformed(ActionEvent e)
2605       {
2606         SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2607         AlignmentSorter.sortByTree(viewport.getAlignment(),
2608                                    treePanel.getTree());
2609
2610         addHistoryItem(new OrderCommand("Tree Sort",
2611                                         oldOrder,
2612                                         viewport.alignment));
2613
2614
2615         alignPanel.repaint();
2616       }
2617     });
2618
2619     treePanel.addInternalFrameListener(new javax.swing.event.
2620                                        InternalFrameAdapter()
2621     {
2622       public void internalFrameClosed(
2623           javax.swing.event.InternalFrameEvent evt)
2624       {
2625         treeCount--;
2626         sortByTreeMenu.remove(item);
2627
2628         if (treeCount == 0)
2629         {
2630           sort.remove(sortByTreeMenu);
2631         }
2632       }
2633       ;
2634     });
2635   }
2636
2637   /**
2638    * Work out whether the whole set of sequences
2639    * or just the selected set will be submitted for multiple alignment.
2640    *
2641    */
2642   private jalview.datamodel.AlignmentView gatherSequencesForAlignment()
2643   {
2644     // Now, check we have enough sequences
2645     AlignmentView msa = null;
2646
2647     if ( (viewport.getSelectionGroup() != null) &&
2648         (viewport.getSelectionGroup().getSize(false) > 1))
2649     {
2650       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
2651       /*SequenceGroup seqs = viewport.getSelectionGroup();
2652       int sz;
2653       msa = new SequenceI[sz = seqs.getSize(false)];
2654
2655       for (int i = 0; i < sz; i++)
2656       {
2657         msa[i] = (SequenceI) seqs.getSequenceAt(i);
2658       } */
2659       msa = viewport.getAlignmentView(true);
2660     }
2661     else
2662     {
2663       /*Vector seqs = viewport.getAlignment().getSequences();
2664
2665       if (seqs.size() > 1)
2666       {
2667         msa = new SequenceI[seqs.size()];
2668
2669         for (int i = 0; i < seqs.size(); i++)
2670         {
2671           msa[i] = (SequenceI) seqs.elementAt(i);
2672         }
2673       }*/
2674       msa = viewport.getAlignmentView(false);
2675     }
2676     return msa;
2677   }
2678
2679   /**
2680    * Decides what is submitted to a secondary structure prediction service,
2681    * the currently selected sequence, or the currently selected alignment
2682    * (where the first sequence in the set is the one that the prediction
2683    * will be for).
2684    */
2685   AlignmentView gatherSeqOrMsaForSecStrPrediction()
2686   {
2687    AlignmentView seqs = null;
2688
2689     if ( (viewport.getSelectionGroup() != null) &&
2690         (viewport.getSelectionGroup().getSize(false) > 0))
2691     {
2692       seqs = viewport.getAlignmentView(true);
2693     }
2694     else
2695     {
2696       seqs = viewport.getAlignmentView(false);
2697     }
2698     // limit sequences - JBPNote in future - could spawn multiple prediction jobs
2699     // TODO: viewport.alignment.isAligned is a global state - the local selection may well be aligned - we preserve 2.0.8 behaviour for moment.
2700     if (!viewport.alignment.isAligned())
2701     {
2702       seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] } );
2703     }
2704     return seqs;
2705   }
2706   /**
2707    * DOCUMENT ME!
2708    *
2709    * @param e DOCUMENT ME!
2710    */
2711   protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)
2712   {
2713     // Pick the tree file
2714     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2715         getProperty(
2716             "LAST_DIRECTORY"));
2717     chooser.setFileView(new JalviewFileView());
2718     chooser.setDialogTitle("Select a newick-like tree file");
2719     chooser.setToolTipText("Load a tree file");
2720
2721     int value = chooser.showOpenDialog(null);
2722
2723     if (value == JalviewFileChooser.APPROVE_OPTION)
2724     {
2725       String choice = chooser.getSelectedFile().getPath();
2726       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
2727
2728       try
2729       {
2730         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,
2731             "File");
2732         viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
2733       }
2734       catch (Exception ex)
2735       {
2736         JOptionPane.showMessageDialog(Desktop.desktop,
2737                                       "Problem reading tree file",
2738                                       ex.getMessage(),
2739                                       JOptionPane.WARNING_MESSAGE);
2740         ex.printStackTrace();
2741       }
2742     }
2743   }
2744
2745
2746   public TreePanel ShowNewickTree(NewickFile nf, String title)
2747   {
2748     return ShowNewickTree(nf,title,600,500,4,5);
2749   }
2750   public TreePanel ShowNewickTree(NewickFile nf, String title, AlignmentView input)
2751   {
2752     return ShowNewickTree(nf,title, input, 600,500,4,5);
2753   }
2754   public TreePanel ShowNewickTree(NewickFile nf, String title, int w,int h,int x, int y) {
2755     return ShowNewickTree(nf, title, null, w, h, x, y);
2756   }
2757   /**
2758    * Add a treeviewer for the tree extracted from a newick file object to the current alignment view
2759    *
2760    * @param nf the tree
2761    * @param title tree viewer title
2762    * @param input Associated alignment input data (or null)
2763    * @param w width
2764    * @param h height
2765    * @param x position
2766    * @param y position
2767    * @return TreePanel handle
2768    */
2769   public TreePanel ShowNewickTree(NewickFile nf, String title, AlignmentView input, int w,int h,int x, int y) {
2770     TreePanel tp = null;
2771
2772     try
2773     {
2774       nf.parse();
2775
2776       if (nf.getTree() != null)
2777       {
2778         tp = new TreePanel(alignPanel,
2779                            "FromFile",
2780                            title,
2781                            nf, input);
2782
2783         tp.setSize(w,h);
2784
2785         if(x>0 && y>0)
2786           tp.setLocation(x,y);
2787
2788
2789         Desktop.addInternalFrame(tp, title, w, h);
2790         addTreeMenuItem(tp, title);
2791       }
2792     }
2793     catch (Exception ex)
2794     {
2795       ex.printStackTrace();
2796     }
2797
2798     return tp;
2799   }
2800
2801   class PrintThread
2802       extends Thread
2803   {
2804     public void run()
2805     {
2806       PrinterJob printJob = PrinterJob.getPrinterJob();
2807       PageFormat pf = printJob.pageDialog(printJob.defaultPage());
2808       printJob.setPrintable(alignPanel, pf);
2809
2810       if (printJob.printDialog())
2811       {
2812         try
2813         {
2814           printJob.print();
2815         }
2816         catch (Exception PrintException)
2817         {
2818           PrintException.printStackTrace();
2819         }
2820       }
2821     }
2822   }
2823
2824   /**
2825    * Generates menu items and listener event actions for web service clients
2826    *
2827    */
2828   public void BuildWebServiceMenu()
2829   {
2830     if ( (Discoverer.services != null)
2831         && (Discoverer.services.size() > 0))
2832     {
2833       Vector msaws = (Vector) Discoverer.services.get("MsaWS");
2834       Vector secstrpr = (Vector) Discoverer.services.get("SecStrPred");
2835       Vector wsmenu = new Vector();
2836       final AlignFrame af = this;
2837       if (msaws != null)
2838       {
2839         // Add any Multiple Sequence Alignment Services
2840         final JMenu msawsmenu = new JMenu("Alignment");
2841         for (int i = 0, j = msaws.size(); i < j; i++)
2842         {
2843           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.
2844               get(i);
2845           final JMenuItem method = new JMenuItem(sh.getName());
2846           method.addActionListener(new ActionListener()
2847           {
2848             public void actionPerformed(ActionEvent e)
2849             {
2850               AlignmentView msa = gatherSequencesForAlignment();
2851               new jalview.ws.MsaWSClient(sh, title, msa,
2852                   false, true, viewport.getAlignment().getDataset(), af);
2853
2854             }
2855
2856           });
2857           msawsmenu.add(method);
2858           // Deal with services that we know accept partial alignments.
2859           if (sh.getName().indexOf("lustal") > -1)
2860           {
2861             // We know that ClustalWS can accept partial alignments for refinement.
2862             final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");
2863             methodR.addActionListener(new ActionListener()
2864             {
2865               public void actionPerformed(ActionEvent e)
2866               {
2867                 AlignmentView msa = gatherSequencesForAlignment();
2868                 new jalview.ws.MsaWSClient(sh, title, msa,
2869                     true, true, viewport.getAlignment().getDataset(), af);
2870
2871               }
2872
2873             });
2874             msawsmenu.add(methodR);
2875
2876           }
2877         }
2878         wsmenu.add(msawsmenu);
2879       }
2880       if (secstrpr != null)
2881       {
2882         // Add any secondary structure prediction services
2883         final JMenu secstrmenu = new JMenu("Secondary Structure Prediction");
2884         for (int i = 0, j = secstrpr.size(); i < j; i++)
2885         {
2886           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)
2887               secstrpr.get(i);
2888           final JMenuItem method = new JMenuItem(sh.getName());
2889           method.addActionListener(new ActionListener()
2890           {
2891             public void actionPerformed(ActionEvent e)
2892             {
2893               AlignmentView msa = gatherSeqOrMsaForSecStrPrediction();
2894               if (msa.getSequences().length == 1)
2895               {
2896                 // Single Sequence prediction
2897                 new jalview.ws.JPredClient(sh, title, false, msa, af, true);
2898               }
2899               else
2900               {
2901                 if (msa.getSequences().length > 1)
2902                 {
2903                   // Sequence profile based prediction
2904                   new jalview.ws.JPredClient(sh,
2905                       title, true, msa, af, true);
2906                 }
2907               }
2908             }
2909           });
2910           secstrmenu.add(method);
2911         }
2912         wsmenu.add(secstrmenu);
2913       }
2914       this.webService.removeAll();
2915       for (int i = 0, j = wsmenu.size(); i < j; i++)
2916       {
2917         webService.add( (JMenu) wsmenu.get(i));
2918       }
2919     }
2920     else
2921     {
2922       this.webService.removeAll();
2923       this.webService.add(this.webServiceNoServices);
2924     }
2925     // TODO: add in rediscovery function
2926     // TODO: reduce code redundancy.
2927     // TODO: group services by location as well as function.
2928   }
2929
2930  /* public void vamsasStore_actionPerformed(ActionEvent e)
2931   {
2932     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2933         getProperty("LAST_DIRECTORY"));
2934
2935     chooser.setFileView(new JalviewFileView());
2936     chooser.setDialogTitle("Export to Vamsas file");
2937     chooser.setToolTipText("Export");
2938
2939     int value = chooser.showSaveDialog(this);
2940
2941     if (value == JalviewFileChooser.APPROVE_OPTION)
2942     {
2943       jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);
2944       //vs.store(chooser.getSelectedFile().getAbsolutePath()   );
2945       vs.storeJalview( chooser.getSelectedFile().getAbsolutePath(), this);
2946     }
2947   }*/
2948
2949
2950
2951
2952 public void showTranslation_actionPerformed(ActionEvent e)
2953 {
2954   SequenceI [] selection = viewport.getSelectionAsNewSequence();
2955   String [] seqstring = viewport.getViewAsString(true);
2956
2957   int s, sSize = selection.length;
2958   SequenceI [] newSeq = new SequenceI[sSize];
2959
2960   int res, resSize;
2961   StringBuffer protein;
2962   String seq;
2963   for(s=0; s<sSize; s++)
2964   {
2965     protein = new StringBuffer();
2966     seq = AlignSeq.extractGaps("-. ", seqstring[s]);
2967     resSize = seq.length();
2968     resSize -= resSize%3;
2969
2970     for(res = 0; res < resSize; res+=3)
2971     {
2972       String codon = seq.substring(res, res+3);
2973       codon = codon.replace('U', 'T');
2974       String aa = ResidueProperties.codonTranslate(codon);
2975       if(aa==null)
2976         protein.append(viewport.getGapCharacter());
2977       else if(aa.equals("STOP"))
2978         protein.append("X");
2979       else
2980         protein.append( aa );
2981     }
2982     newSeq[s] = new Sequence(selection[s].getName(),
2983                              protein.toString());
2984   }
2985
2986
2987   AlignmentI al = new Alignment(newSeq);
2988   al.setDataset(null);
2989
2990
2991   ////////////////////////////////
2992   // Copy annotations across
2993   jalview.datamodel.AlignmentAnnotation[] annotations
2994       = viewport.alignment.getAlignmentAnnotation();
2995   int a, aSize;
2996   if(annotations!=null)
2997   {
2998     for (int i = 0; i < annotations.length; i++)
2999     {
3000       if (annotations[i].label.equals("Quality") ||
3001           annotations[i].label.equals("Conservation") ||
3002           annotations[i].label.equals("Consensus"))
3003       {
3004         continue;
3005       }
3006
3007       aSize = viewport.alignment.getWidth() / 3;
3008       jalview.datamodel.Annotation[] anots =
3009           new jalview.datamodel.Annotation[aSize];
3010
3011       for (a = 0; a < viewport.alignment.getWidth(); a++)
3012       {
3013         if (annotations[i].annotations[a] == null
3014             || annotations[i].annotations[a] == null)
3015           continue;
3016
3017         anots[a / 3] = new Annotation(
3018             annotations[i].annotations[a].displayCharacter,
3019             annotations[i].annotations[a].description,
3020             annotations[i].annotations[a].secondaryStructure,
3021             annotations[i].annotations[a].value,
3022             annotations[i].annotations[a].colour);
3023       }
3024
3025       jalview.datamodel.AlignmentAnnotation aa
3026           = new jalview.datamodel.AlignmentAnnotation(annotations[i].label,
3027           annotations[i].description, anots);
3028       al.addAnnotation(aa);
3029     }
3030   }
3031
3032     AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
3033     Desktop.addInternalFrame(af, "Translation of "+this.getTitle(),
3034                              DEFAULT_WIDTH,
3035                              DEFAULT_HEIGHT);
3036
3037
3038
3039
3040 }
3041
3042 /**
3043  * DOCUMENT ME!
3044  *
3045  * @param String DOCUMENT ME!
3046  */
3047 public boolean parseFeaturesFile(String file, String type)
3048 {
3049     boolean featuresFile = false;
3050     try{
3051       featuresFile = new FeaturesFile(file, type).parse(viewport.alignment.getDataset(),
3052                                          alignPanel.seqPanel.seqCanvas.
3053                                          getFeatureRenderer().featureColours,
3054                                          false);
3055     }
3056     catch(Exception ex)
3057     {
3058       ex.printStackTrace();
3059     }
3060
3061     if(featuresFile)
3062     {
3063       viewport.showSequenceFeatures = true;
3064       showSeqFeatures.setSelected(true);
3065       alignPanel.repaint();
3066     }
3067
3068     return featuresFile;
3069 }
3070
3071 public void dragEnter(DropTargetDragEvent evt)
3072 {}
3073
3074 public void dragExit(DropTargetEvent evt)
3075 {}
3076
3077 public void dragOver(DropTargetDragEvent evt)
3078 {}
3079
3080 public void dropActionChanged(DropTargetDragEvent evt)
3081 {}
3082
3083 public void drop(DropTargetDropEvent evt)
3084 {
3085     Transferable t = evt.getTransferable();
3086     java.util.List files = null;
3087
3088     try
3089     {
3090       DataFlavor uriListFlavor = new DataFlavor("text/uri-list;class=java.lang.String");
3091       if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3092       {
3093         //Works on Windows and MacOSX
3094         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3095         files = (java.util.List) t.getTransferData(DataFlavor.javaFileListFlavor);
3096       }
3097       else if (t.isDataFlavorSupported(uriListFlavor))
3098       {
3099         // This is used by Unix drag system
3100         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3101         String data = (String) t.getTransferData(uriListFlavor);
3102         files = new java.util.ArrayList(1);
3103         for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3104             data,
3105             "\r\n");
3106              st.hasMoreTokens(); )
3107         {
3108           String s = st.nextToken();
3109           if (s.startsWith("#"))
3110           {
3111             // the line is a comment (as per the RFC 2483)
3112             continue;
3113           }
3114
3115           java.net.URI uri = new java.net.URI(s);
3116           java.io.File file = new java.io.File(uri);
3117           files.add(file);
3118         }
3119       }
3120     }
3121     catch (Exception e)
3122     {
3123       e.printStackTrace();
3124     }
3125     if (files != null)
3126     {
3127       try
3128       {
3129
3130         for (int i = 0; i < files.size(); i++)
3131         {
3132           loadJalviewDataFile(files.get(i).toString());
3133         }
3134       }
3135       catch (Exception ex)
3136       {
3137         ex.printStackTrace();
3138       }
3139     }
3140 }
3141
3142   // This method will attempt to load a "dropped" file first by testing
3143   // whether its and Annotation file, then features file. If both are
3144   // false then the user may have dropped an alignment file onto this
3145   // AlignFrame
3146    public void loadJalviewDataFile(String file)
3147   {
3148     try{
3149       String protocol = "File";
3150
3151       if (file.indexOf("http:") > -1 || file.indexOf("file:") > -1)
3152       {
3153         protocol = "URL";
3154       }
3155
3156       boolean isAnnotation = new AnnotationFile().readAnnotationFile(viewport.
3157           alignment, file);
3158
3159       if (!isAnnotation)
3160       {
3161         boolean isGroupsFile = parseFeaturesFile(file,protocol);
3162         if (!isGroupsFile)
3163         {
3164           String format = new IdentifyFile().Identify(file, protocol);
3165
3166           if(format.equalsIgnoreCase("JnetFile"))
3167           {
3168             jalview.io.JPredFile predictions = new jalview.io.JPredFile(
3169                 file, protocol);
3170             new JnetAnnotationMaker().add_annotation(predictions,
3171                 viewport.getAlignment(),
3172                 0, false);
3173             alignPanel.adjustAnnotationHeight();
3174             alignPanel.repaint();
3175           }
3176           else
3177             new FileLoader().LoadFile(viewport, file, protocol, format);
3178         }
3179       }
3180       else
3181       {
3182         // (isAnnotation)
3183         alignPanel.adjustAnnotationHeight();
3184       }
3185
3186     }catch(Exception ex)
3187     {
3188       ex.printStackTrace();
3189     }
3190   }
3191
3192   public void tabSelectionChanged(int index)
3193   {
3194     if (index > -1)
3195     {
3196       alignPanel = (AlignmentPanel) alignPanels.elementAt(index);
3197       viewport = alignPanel.av;
3198       setMenusFromViewport(viewport);
3199     }
3200   }
3201
3202   public void tabbedPane_mousePressed(MouseEvent e)
3203   {
3204     if(SwingUtilities.isRightMouseButton(e))
3205     {
3206       String reply = JOptionPane.showInternalInputDialog(this,
3207           "Enter View Name",
3208           "Edit View Name",
3209           JOptionPane.QUESTION_MESSAGE);
3210
3211       if (reply != null)
3212       {
3213         viewport.viewName = reply;
3214         tabbedPane.setTitleAt( tabbedPane.getSelectedIndex() ,reply);
3215       }
3216     }
3217   }
3218
3219
3220   public AlignViewport getCurrentView()
3221   {
3222     return viewport;
3223   }
3224 }