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