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