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