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