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