FeatureRenderer takes alignmentPanel
[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                (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0 &&
178                 evt.getKeyCode() <= KeyEvent.VK_NUMPAD9)
179               )
180               && Character.isDigit(evt.getKeyChar()))
181             alignPanel.seqPanel.numberPressed(evt.getKeyChar());
182
183
184           switch (evt.getKeyCode())
185           {
186
187             case 27: // escape key
188               deselectAllSequenceMenuItem_actionPerformed(null);
189
190               break;
191
192             case KeyEvent.VK_DOWN:
193              if (evt.isAltDown() || !viewport.cursorMode)
194               moveSelectedSequences(false);
195               if (viewport.cursorMode)
196                 alignPanel.seqPanel.moveCursor(0, 1);
197               break;
198
199             case KeyEvent.VK_UP:
200             if (evt.isAltDown() || !viewport.cursorMode)
201               moveSelectedSequences(true);
202               if (viewport.cursorMode)
203                 alignPanel.seqPanel.moveCursor(0, -1);
204
205               break;
206
207             case KeyEvent.VK_LEFT:
208             if (evt.isAltDown() || !viewport.cursorMode)
209               slideSequences(false,
210                              alignPanel.seqPanel.getKeyboardNo1());
211             else
212                 alignPanel.seqPanel.moveCursor( -1, 0);
213
214
215               break;
216
217             case KeyEvent.VK_RIGHT:
218             if (evt.isAltDown() || !viewport.cursorMode)
219               slideSequences(true,
220                              alignPanel.seqPanel.getKeyboardNo1());
221             else
222                 alignPanel.seqPanel.moveCursor(1, 0);
223               break;
224
225             case KeyEvent.VK_SPACE:
226               if (viewport.cursorMode)
227               {
228                 alignPanel.seqPanel.insertGapAtCursor(evt.isControlDown()
229                                            || evt.isShiftDown()
230                                            || evt.isAltDown());
231               }
232               break;
233
234             case KeyEvent.VK_DELETE:
235             case KeyEvent.VK_BACK_SPACE:
236               if (!viewport.cursorMode)
237               {
238                 cut_actionPerformed(null);
239               }
240               else
241             {
242                 alignPanel.seqPanel.deleteGapAtCursor(evt.isControlDown()
243                                            || evt.isShiftDown()
244                                            || evt.isAltDown());
245             }
246
247               break;
248
249             case KeyEvent.VK_S:
250               if (viewport.cursorMode)
251               {
252                 alignPanel.seqPanel.setCursorRow();
253               }
254               break;
255             case KeyEvent.VK_C:
256               if (viewport.cursorMode && !evt.isControlDown())
257               {
258                 alignPanel.seqPanel.setCursorColumn();
259               }
260               break;
261             case KeyEvent.VK_P:
262               if (viewport.cursorMode)
263               {
264                 alignPanel.seqPanel.setCursorPosition();
265               }
266               break;
267
268             case KeyEvent.VK_ENTER:
269             case KeyEvent.VK_COMMA:
270               if (viewport.cursorMode)
271               {
272                 alignPanel.seqPanel.setCursorRowAndColumn();
273               }
274               break;
275
276             case KeyEvent.VK_Q:
277               if (viewport.cursorMode)
278               {
279                 alignPanel.seqPanel.setSelectionAreaAtCursor(true);
280               }
281               break;
282             case KeyEvent.VK_M:
283               if (viewport.cursorMode)
284               {
285                 alignPanel.seqPanel.setSelectionAreaAtCursor(false);
286               }
287               break;
288
289             case KeyEvent.VK_F2:
290               viewport.cursorMode = !viewport.cursorMode;
291               statusBar.setText("Keyboard editing mode is " +
292                                            (viewport.cursorMode ? "on" : "off"));
293               if (viewport.cursorMode)
294               {
295                 alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;
296                 alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;
297               }
298               alignPanel.seqPanel.seqCanvas.repaint();
299               break;
300
301             case KeyEvent.VK_F1:
302               try
303               {
304                 ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
305                 java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
306                 javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
307
308                 javax.help.HelpBroker hb = hs.createHelpBroker();
309                 hb.setCurrentID("home");
310                 hb.setDisplayed(true);
311               }
312               catch (Exception ex)
313               {
314                 ex.printStackTrace();
315               }
316               break
317                   ;
318             case KeyEvent.VK_H:
319             {
320               boolean toggleSeqs = !evt.isControlDown();
321               boolean toggleCols = !evt.isShiftDown();
322
323               boolean hide = false;
324
325               SequenceGroup sg = viewport.getSelectionGroup();
326               if (toggleSeqs)
327               {
328                 if (sg != null && sg.getSize() != viewport.alignment.getHeight())
329                 {
330                   hideSelSequences_actionPerformed(null);
331                   hide = true;
332                 }
333               else if (! (toggleCols &&
334                           viewport.colSel.getSelected().size() > 0))
335               {
336                   showAllSeqs_actionPerformed(null);
337               }
338             }
339
340               if (toggleCols)
341               {
342                 if (viewport.colSel.getSelected().size() > 0)
343                 {
344                   hideSelColumns_actionPerformed(null);
345                   if (!toggleSeqs)
346                 {
347                     viewport.selectionGroup = sg;
348                 }
349               }
350                 else if (!hide)
351               {
352                   showAllColumns_actionPerformed(null);
353               }
354             }
355               break;
356             }
357             case KeyEvent.VK_PAGE_UP:
358               if (viewport.wrapAlignment)
359             {
360                 alignPanel.scrollUp(true);
361             }
362               else
363             {
364                 alignPanel.setScrollValues(viewport.startRes,
365                                            viewport.startSeq
366                                            - viewport.endSeq + viewport.startSeq);
367             }
368               break;
369             case KeyEvent.VK_PAGE_DOWN:
370               if (viewport.wrapAlignment)
371             {
372                 alignPanel.scrollUp(false);
373             }
374               else
375             {
376                 alignPanel.setScrollValues(viewport.startRes,
377                                            viewport.startSeq
378                                            + viewport.endSeq - viewport.startSeq);
379             }
380               break;
381           }
382         }
383
384       public void keyReleased(KeyEvent evt)
385       {
386         switch(evt.getKeyCode())
387         {
388           case KeyEvent.VK_LEFT:
389             if (evt.isAltDown() || !viewport.cursorMode)
390               viewport.firePropertyChange("alignment", null,
391                                           viewport.getAlignment().getSequences());
392             break;
393
394           case KeyEvent.VK_RIGHT:
395             if (evt.isAltDown() || !viewport.cursorMode)
396               viewport.firePropertyChange("alignment", null,
397                                           viewport.getAlignment().getSequences());
398             break;
399         }
400       }
401       });
402   }
403
404
405   public void addAlignmentPanel(final AlignmentPanel ap,
406                                 boolean newPanel)
407   {
408     ap.alignFrame = this;
409
410     alignPanels.addElement(ap);
411
412     PaintRefresher.Register(ap, ap.av.getSequenceSetId());
413
414     int aSize = alignPanels.size();
415
416     tabbedPane.setVisible(aSize>1 || ap.av.viewName!=null);
417
418     if (aSize == 1 && ap.av.viewName==null)
419     {
420       this.getContentPane().add(ap, BorderLayout.CENTER);
421     }
422     else
423     {
424       if (aSize == 2)
425       {
426         setInitialTabVisible();
427       }
428
429       expandViews.setEnabled(true);
430       gatherViews.setEnabled(true);
431       tabbedPane.addTab(ap.av.viewName, ap);
432
433       ap.setVisible(false);
434     }
435
436     if(newPanel)
437     {
438       if (ap.av.padGaps)
439       {
440         ap.av.alignment.padGaps();
441       }
442       ap.av.updateConservation(ap);
443       ap.av.updateConsensus(ap);
444     }
445   }
446
447   public void setInitialTabVisible()
448   {
449     expandViews.setEnabled(true);
450     gatherViews.setEnabled(true);
451     tabbedPane.setVisible(true);
452     AlignmentPanel first = (AlignmentPanel) alignPanels.firstElement();
453     tabbedPane.addTab(first.av.viewName,first);
454     this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
455   }
456
457
458   public AlignViewport getViewport()
459   {
460     return viewport;
461   }
462
463   /* Set up intrinsic listeners for dynamically generated GUI bits. */
464   private void addServiceListeners()
465   {
466     final java.beans.PropertyChangeListener thisListener;
467     // Do this once to get current state
468     BuildWebServiceMenu();
469     Desktop.discoverer.addPropertyChangeListener(
470         thisListener = new java.beans.PropertyChangeListener()
471     {
472       public void propertyChange(PropertyChangeEvent evt)
473       {
474         // System.out.println("Discoverer property change.");
475         if (evt.getPropertyName().equals("services"))
476         {
477           // System.out.println("Rebuilding web service menu");
478           BuildWebServiceMenu();
479         }
480       }
481     });
482
483     addInternalFrameListener(new javax.swing.event.
484                              InternalFrameAdapter()
485     {
486       public void internalFrameClosed(
487           javax.swing.event.InternalFrameEvent evt)
488       {
489         // System.out.println("deregistering discoverer listener");
490         Desktop.discoverer.removePropertyChangeListener(thisListener);
491         closeMenuItem_actionPerformed(true);
492       }
493       ;
494     });
495   }
496
497   public void setGUINucleotide(boolean nucleotide)
498   {
499     showTranslation.setVisible( nucleotide );
500     conservationMenuItem.setEnabled( !nucleotide );
501     modifyConservation.setEnabled(   !nucleotide );
502
503     //Remember AlignFrame always starts as protein
504     if(!nucleotide)
505     {
506       calculateMenu.remove(calculateMenu.getItemCount()-2);
507     }
508   }
509
510   /**
511    * Need to call this method when tabs are selected for multiple views,
512    * or when loading from Jalview2XML.java
513    * @param av AlignViewport
514    */
515   void setMenusFromViewport(AlignViewport av)
516   {
517     padGapsMenuitem.setSelected(av.padGaps);
518     colourTextMenuItem.setSelected(av.showColourText);
519     abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
520     conservationMenuItem.setSelected(av.getConservationSelected());
521     seqLimits.setSelected(av.getShowJVSuffix());
522     idRightAlign.setSelected(av.rightAlignIds);
523     renderGapsMenuItem.setSelected(av.renderGaps);
524     wrapMenuItem.setSelected(av.wrapAlignment);
525     scaleAbove.setVisible(av.wrapAlignment);
526     scaleLeft.setVisible(av.wrapAlignment);
527     scaleRight.setVisible(av.wrapAlignment);
528     annotationPanelMenuItem.setState(av.showAnnotation);
529     viewBoxesMenuItem.setSelected(av.showBoxes);
530     viewTextMenuItem.setSelected(av.showText);
531
532     setColourSelected(ColourSchemeProperty.
533                       getColourName(av.getGlobalColourScheme()));
534
535     showSeqFeatures.setSelected(av.showSequenceFeatures);
536     hiddenMarkers.setState(av.showHiddenMarkers);
537     applyToAllGroups.setState(av.colourAppliesToAllGroups);
538
539     updateEditMenuBar();
540   }
541
542
543   Hashtable progressBars;
544   public void setProgressBar(String message, long id)
545   {
546     if(progressBars == null)
547     {
548       progressBars = new Hashtable();
549     }
550
551     JPanel progressPanel;
552     GridLayout layout = (GridLayout) statusPanel.getLayout();
553     if(progressBars.get( new Long(id) )!=null)
554      {
555        progressPanel = (JPanel)progressBars.get( new Long(id) );
556        statusPanel.remove(progressPanel);
557        progressBars.remove( progressPanel );
558        progressPanel = null;
559        if(message!=null)
560       {
561          statusBar.setText(message);
562       }
563
564        layout.setRows(layout.getRows() - 1);
565      }
566     else
567     {
568       progressPanel = new JPanel(new BorderLayout(10, 5));
569
570       JProgressBar progressBar = new JProgressBar();
571       progressBar.setIndeterminate(true);
572
573       progressPanel.add(new JLabel(message), BorderLayout.WEST);
574       progressPanel.add(progressBar, BorderLayout.CENTER);
575
576       layout.setRows(layout.getRows() + 1);
577       statusPanel.add(progressPanel);
578
579       progressBars.put(new Long(id), progressPanel);
580     }
581
582     validate();
583   }
584
585
586
587
588   /*
589    Added so Castor Mapping file can obtain Jalview Version
590   */
591   public String getVersion()
592   {
593     return  jalview.bin.Cache.getProperty("VERSION");
594   }
595
596   public FeatureRenderer getFeatureRenderer()
597   {
598     return alignPanel.seqPanel.seqCanvas.getFeatureRenderer();
599   }
600
601
602   public void fetchSequence_actionPerformed(ActionEvent e)
603   {
604     new SequenceFetcher(this);
605   }
606
607   public void addFromFile_actionPerformed(ActionEvent e)
608   {
609     Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
610   }
611
612   public void reload_actionPerformed(ActionEvent e)
613   {
614     if(fileName!=null)
615     {
616       if(currentFileFormat.equals("Jalview"))
617       {
618         JInternalFrame [] frames = Desktop.desktop.getAllFrames();
619         for(int i=0; i<frames.length; i++)
620         {
621           if (frames[i] instanceof AlignFrame
622               && frames[i] != this
623               && ( (AlignFrame) frames[i]).fileName.equals(fileName))
624           {
625             try
626             {
627               frames[i].setSelected(true);
628               Desktop.instance.closeAssociatedWindows();
629           }
630             catch (java.beans.PropertyVetoException ex)
631             {}
632           }
633
634         }
635         Desktop.instance.closeAssociatedWindows();
636
637         FileLoader loader = new FileLoader();
638         String protocol = fileName.startsWith("http:")? "URL":"File";
639         loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
640       }
641       else
642       {
643         Rectangle bounds = this.getBounds();
644
645         FileLoader loader = new FileLoader();
646         String protocol = fileName.startsWith("http:") ? "URL" : "File";
647         AlignFrame newframe =
648             loader.LoadFileWaitTillLoaded(fileName, protocol, currentFileFormat);
649
650         newframe.setBounds(bounds);
651
652         this.closeMenuItem_actionPerformed(true);
653       }
654     }
655   }
656
657
658   public void addFromText_actionPerformed(ActionEvent e)
659   {
660     Desktop.instance.inputTextboxMenuItem_actionPerformed(viewport);
661   }
662
663   public void addFromURL_actionPerformed(ActionEvent e)
664   {
665     Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
666   }
667
668
669   public void save_actionPerformed(ActionEvent e)
670   {
671     if(fileName==null
672        || currentFileFormat==null
673        || fileName.startsWith("http")
674         )
675     {
676       saveAs_actionPerformed(null);
677     }
678     else
679     {
680       saveAlignment(fileName, currentFileFormat);
681   }
682   }
683
684   /**
685    * DOCUMENT ME!
686    *
687    * @param e DOCUMENT ME!
688    */
689   public void saveAs_actionPerformed(ActionEvent e)
690   {
691     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
692         getProperty( "LAST_DIRECTORY"),
693         new String[]
694         { "fa, fasta, fastq", "aln", "pfam", "msf", "pir", "blc","jar" },
695         new String[]
696         { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview" },
697         currentFileFormat,
698         false);
699
700
701     chooser.setFileView(new JalviewFileView());
702     chooser.setDialogTitle("Save Alignment to file");
703     chooser.setToolTipText("Save");
704
705     int value = chooser.showSaveDialog(this);
706
707     if (value == JalviewFileChooser.APPROVE_OPTION)
708     {
709         currentFileFormat = chooser.getSelectedFormat();
710         if (currentFileFormat == null)
711         {
712           JOptionPane.showInternalMessageDialog(Desktop.desktop,
713                                                 "You must select a file format before saving!",
714                                                 "File format not specified",
715                                                 JOptionPane.WARNING_MESSAGE);
716           value = chooser.showSaveDialog(this);
717           return;
718         }
719
720         fileName = chooser.getSelectedFile().getPath();
721
722       jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT",
723                                     currentFileFormat);
724
725       jalview.bin.Cache.setProperty("LAST_DIRECTORY", fileName);
726
727       saveAlignment(fileName, currentFileFormat);
728     }
729   }
730
731   public boolean saveAlignment(String file, String format)
732   {
733     boolean success = true;
734
735     if (format.equalsIgnoreCase("Jalview"))
736     {
737       String shortName = title;
738
739       if (shortName.indexOf(java.io.File.separatorChar) > -1)
740       {
741         shortName = shortName.substring(shortName.lastIndexOf(
742             java.io.File.separatorChar) + 1);
743       }
744
745       success = new Jalview2XML().SaveAlignment(this, file, shortName);
746
747       statusBar.setText("Successfully saved to file: "
748                           +fileName+" in "
749                           +format +" format.");
750
751     }
752     else
753     {
754
755       String[] omitHidden = null;
756
757       if (viewport.hasHiddenColumns)
758       {
759         int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
760             "The Alignment contains hidden columns."
761             + "\nDo you want to save only the visible alignment?",
762             "Save / Omit Hidden Columns",
763             JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
764
765         if (reply == JOptionPane.YES_OPTION)
766         {
767           omitHidden = viewport.getViewAsString(false);
768       }
769       }
770
771       String output = new FormatAdapter().formatSequences(
772           format,
773           viewport.alignment.getSequencesArray(),
774           omitHidden);
775
776       if (output == null)
777       {
778         success = false;
779       }
780       else
781       {
782         try
783         {
784           java.io.PrintWriter out = new java.io.PrintWriter(
785               new java.io.FileWriter(file));
786
787           out.print(output);
788           out.close();
789           this.setTitle(file);
790           statusBar.setText("Successfully saved to file: "
791                             + fileName + " in "
792                             + format + " format.");
793         }
794         catch (Exception ex)
795         {
796           success = false;
797           ex.printStackTrace();
798         }
799       }
800     }
801
802     if (!success)
803     {
804       JOptionPane.showInternalMessageDialog(
805           this, "Couldn't save file: " + fileName,
806           "Error Saving File",
807           JOptionPane.WARNING_MESSAGE);
808     }
809
810     return success;
811   }
812
813   /**
814    * DOCUMENT ME!
815    *
816    * @param e DOCUMENT ME!
817    */
818   protected void outputText_actionPerformed(ActionEvent e)
819   {
820     String [] omitHidden = null;
821
822     if(viewport.hasHiddenColumns)
823     {
824       int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
825           "The Alignment contains hidden columns."
826       +"\nDo you want to output only the visible alignment?",
827       "Save / Omit Hidden Columns",
828       JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
829
830       if(reply==JOptionPane.YES_OPTION)
831       {
832         omitHidden = viewport.getViewAsString(false);
833       }
834     }
835
836     CutAndPasteTransfer cap = new CutAndPasteTransfer();
837     cap.setForInput(null);
838     Desktop.addInternalFrame(cap,
839                              "Alignment output - " + e.getActionCommand(), 600,
840                              500);
841
842
843     cap.setText(new FormatAdapter().formatSequences(
844         e.getActionCommand(),
845         viewport.alignment.getSequencesArray(),
846         omitHidden));
847   }
848
849   /**
850    * DOCUMENT ME!
851    *
852    * @param e DOCUMENT ME!
853    */
854   protected void htmlMenuItem_actionPerformed(ActionEvent e)
855   {
856     new HTMLOutput(alignPanel,
857                    alignPanel.seqPanel.seqCanvas.getSequenceRenderer(),
858         alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
859   }
860
861   public void createImageMap(File file, String image)
862   {
863     alignPanel.makePNGImageMap(file, image);
864   }
865
866   /**
867    * DOCUMENT ME!
868    *
869    * @param e DOCUMENT ME!
870    */
871   public void createPNG(File f)
872   {
873     alignPanel.makePNG(f);
874   }
875
876   /**
877    * DOCUMENT ME!
878    *
879    * @param e DOCUMENT ME!
880    */
881   public void createEPS(File f)
882   {
883     alignPanel.makeEPS(f);
884   }
885
886
887   public void pageSetup_actionPerformed(ActionEvent e)
888   {
889     PrinterJob printJob = PrinterJob.getPrinterJob();
890     PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
891   }
892
893   /**
894    * DOCUMENT ME!
895    *
896    * @param e DOCUMENT ME!
897    */
898   public void printMenuItem_actionPerformed(ActionEvent e)
899   {
900     //Putting in a thread avoids Swing painting problems
901     PrintThread thread = new PrintThread(alignPanel);
902     thread.start();
903   }
904
905   public void exportFeatures_actionPerformed(ActionEvent e)
906   {
907     new AnnotationExporter().exportFeatures(alignPanel);
908   }
909
910
911   public void exportAnnotations_actionPerformed(ActionEvent e)
912   {
913     new AnnotationExporter().exportAnnotations(
914       alignPanel,
915         viewport.showAnnotation ? viewport.alignment.getAlignmentAnnotation() : null,
916       viewport.alignment.getGroups()
917         );
918   }
919
920
921   public void associatedData_actionPerformed(ActionEvent e)
922   {
923     // Pick the tree file
924     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
925         getProperty(
926             "LAST_DIRECTORY"));
927     chooser.setFileView(new JalviewFileView());
928     chooser.setDialogTitle("Load Jalview Annotations or Features File");
929     chooser.setToolTipText("Load Jalview Annotations / Features file");
930
931     int value = chooser.showOpenDialog(null);
932
933     if (value == JalviewFileChooser.APPROVE_OPTION)
934     {
935       String choice = chooser.getSelectedFile().getPath();
936       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
937       loadJalviewDataFile(choice);
938     }
939
940   }
941
942
943   /**
944    * DOCUMENT ME!
945    *
946    * @param e DOCUMENT ME!
947    */
948   public void closeMenuItem_actionPerformed(boolean closeAllTabs)
949   {
950     if(alignPanels!=null && alignPanels.size()<2)
951     {
952       closeAllTabs = true;
953     }
954
955     try
956     {
957       if(alignPanels!=null)
958       {
959         if (closeAllTabs)
960         {
961           for (int i = 0; i < alignPanels.size(); i++)
962           {
963             AlignmentPanel ap = (AlignmentPanel) alignPanels.elementAt(i);
964             jalview.structure.StructureSelectionManager.getStructureSelectionManager()
965                 .removeStructureViewerListener(ap.seqPanel, null);
966             PaintRefresher.RemoveComponent(ap.seqPanel.seqCanvas);
967             PaintRefresher.RemoveComponent(ap.idPanel.idCanvas);
968             PaintRefresher.RemoveComponent(ap);
969             ap.av.alignment = null;
970           }
971         }
972         else
973         {
974           int index = tabbedPane.getSelectedIndex();
975
976           alignPanels.removeElement(alignPanel);
977           PaintRefresher.RemoveComponent(alignPanel.seqPanel.seqCanvas);
978           PaintRefresher.RemoveComponent(alignPanel.idPanel.idCanvas);
979           PaintRefresher.RemoveComponent(alignPanel);
980           viewport.alignment = null;
981           alignPanel = null;
982           viewport = null;
983
984           tabbedPane.removeTabAt(index);
985           tabbedPane.validate();
986
987           if(index==tabbedPane.getTabCount())
988           {
989             index --;
990           }
991
992           this.tabSelectionChanged(index);
993         }
994       }
995
996       if (closeAllTabs)
997       {
998         this.setClosed(true);
999     }
1000     }
1001     catch (Exception ex)
1002     {
1003       ex.printStackTrace();
1004     }
1005   }
1006
1007
1008   /**
1009    * DOCUMENT ME!
1010    */
1011   void updateEditMenuBar()
1012   {
1013
1014     if (viewport.historyList.size() > 0)
1015     {
1016       undoMenuItem.setEnabled(true);
1017       CommandI command = (CommandI) viewport.historyList.peek();
1018       undoMenuItem.setText("Undo " + command.getDescription());
1019     }
1020     else
1021     {
1022       undoMenuItem.setEnabled(false);
1023       undoMenuItem.setText("Undo");
1024     }
1025
1026     if (viewport.redoList.size() > 0)
1027     {
1028       redoMenuItem.setEnabled(true);
1029
1030       CommandI command = (CommandI) viewport.redoList.peek();
1031       redoMenuItem.setText("Redo " + command.getDescription());
1032     }
1033     else
1034     {
1035       redoMenuItem.setEnabled(false);
1036       redoMenuItem.setText("Redo");
1037     }
1038   }
1039
1040
1041   public void addHistoryItem(CommandI command)
1042   {
1043     if(command.getSize()>0)
1044     {
1045       viewport.historyList.push(command);
1046       viewport.redoList.clear();
1047       updateEditMenuBar();
1048       viewport.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
1049     }
1050   }
1051
1052
1053
1054   /**
1055    * DOCUMENT ME!
1056    *
1057    * @param e DOCUMENT ME!
1058    */
1059   protected void undoMenuItem_actionPerformed(ActionEvent e)
1060   {
1061     CommandI command = (CommandI)viewport.historyList.pop();
1062     viewport.redoList.push(command);
1063     command.undoCommand();
1064
1065     AlignViewport originalSource = getOriginatingSource(command);
1066     updateEditMenuBar();
1067
1068     if(originalSource!=null)
1069     {
1070       originalSource.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
1071       originalSource.firePropertyChange("alignment",
1072                                         null,
1073                                         originalSource.alignment.getSequences());
1074     }
1075   }
1076
1077   /**
1078    * DOCUMENT ME!
1079    *
1080    * @param e DOCUMENT ME!
1081    */
1082   protected void redoMenuItem_actionPerformed(ActionEvent e)
1083   {
1084     if(viewport.redoList.size()<1)
1085     {
1086       return;
1087     }
1088
1089     CommandI command = (CommandI) viewport.redoList.pop();
1090     viewport.historyList.push(command);
1091     command.doCommand();
1092
1093     AlignViewport originalSource = getOriginatingSource(command);
1094     updateEditMenuBar();
1095
1096     if(originalSource!=null)
1097     {
1098       originalSource.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
1099       originalSource.firePropertyChange("alignment",
1100                                         null,
1101                                         originalSource.alignment.getSequences());
1102     }
1103   }
1104
1105   AlignViewport getOriginatingSource(CommandI command)
1106   {
1107     AlignViewport originalSource = null;
1108     //For sequence removal and addition, we need to fire
1109    //the property change event FROM the viewport where the
1110    //original alignment was altered
1111     AlignmentI al=null;
1112     if (command instanceof EditCommand)
1113     {
1114       EditCommand editCommand = (EditCommand) command;
1115       al = editCommand.getAlignment();
1116       Vector comps = (Vector) PaintRefresher.components
1117           .get(viewport.getSequenceSetId());
1118
1119       for (int i = 0; i < comps.size(); i++)
1120       {
1121         if (comps.elementAt(i) instanceof AlignmentPanel)
1122         {
1123           if (al == ( (AlignmentPanel) comps.elementAt(i)).av.alignment)
1124           {
1125             originalSource = ( (AlignmentPanel) comps.elementAt(i)).av;
1126             break;
1127           }
1128         }
1129       }
1130     }
1131
1132     if (originalSource == null)
1133     {
1134       //The original view is closed, we must validate
1135       //the current view against the closed view first
1136       if (al != null)
1137       {
1138         PaintRefresher.validateSequences(al, viewport.alignment);
1139       }
1140
1141       originalSource = viewport;
1142     }
1143
1144     return originalSource;
1145   }
1146
1147   /**
1148    * DOCUMENT ME!
1149    *
1150    * @param up DOCUMENT ME!
1151    */
1152   public void moveSelectedSequences(boolean up)
1153   {
1154     SequenceGroup sg = viewport.getSelectionGroup();
1155
1156     if (sg == null)
1157     {
1158       return;
1159     }
1160
1161     if (up)
1162     {
1163       for (int i = 1; i < viewport.alignment.getHeight(); i++)
1164       {
1165         SequenceI seq = viewport.alignment.getSequenceAt(i);
1166
1167         if (!sg.getSequences(null).contains(seq))
1168         {
1169           continue;
1170         }
1171
1172         SequenceI temp = viewport.alignment.getSequenceAt(i - 1);
1173
1174         if (sg.getSequences(null).contains(temp))
1175         {
1176           continue;
1177         }
1178
1179         viewport.alignment.getSequences().setElementAt(temp, i);
1180         viewport.alignment.getSequences().setElementAt(seq, i - 1);
1181       }
1182     }
1183     else
1184     {
1185       for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)
1186       {
1187         SequenceI seq = viewport.alignment.getSequenceAt(i);
1188
1189         if (!sg.getSequences(null).contains(seq))
1190         {
1191           continue;
1192         }
1193
1194         SequenceI temp = viewport.alignment.getSequenceAt(i + 1);
1195
1196         if (sg.getSequences(null).contains(temp))
1197         {
1198           continue;
1199         }
1200
1201         viewport.alignment.getSequences().setElementAt(temp, i);
1202         viewport.alignment.getSequences().setElementAt(seq, i + 1);
1203       }
1204     }
1205
1206     alignPanel.paintAlignment(true);
1207   }
1208
1209
1210
1211
1212   synchronized void slideSequences(boolean right, int size)
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     newap.av.gatherViewsHere = false;
1974
1975     if (viewport.viewName == null)
1976     {
1977       viewport.viewName = "Original";
1978     }
1979
1980     newap.av.historyList = viewport.historyList;
1981     newap.av.redoList = viewport.redoList;
1982
1983     int index = Desktop.getViewCount(viewport.getSequenceSetId());
1984     String newViewName = "View " +index;
1985
1986     Vector comps = (Vector) PaintRefresher.components.get(viewport.
1987         getSequenceSetId());
1988     Vector existingNames = new Vector();
1989     for(int i=0; i<comps.size(); i++)
1990     {
1991       if(comps.elementAt(i) instanceof AlignmentPanel)
1992       {
1993         AlignmentPanel ap = (AlignmentPanel)comps.elementAt(i);
1994         if(!existingNames.contains(ap.av.viewName))
1995         {
1996           existingNames.addElement(ap.av.viewName);
1997       }
1998     }
1999     }
2000
2001     while(existingNames.contains(newViewName))
2002     {
2003       newViewName = "View "+ (++index);
2004     }
2005
2006     newap.av.viewName = newViewName;
2007
2008     addAlignmentPanel(newap, false);
2009
2010     if(alignPanels.size()==2)
2011     {
2012       viewport.gatherViewsHere = true;
2013     }
2014     tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
2015   }
2016
2017   public void expandViews_actionPerformed(ActionEvent e)
2018   {
2019         Desktop.instance.explodeViews(this);
2020   }
2021
2022   public void gatherViews_actionPerformed(ActionEvent e)
2023   {
2024     Desktop.instance.gatherViews(this);
2025   }
2026
2027
2028
2029   /**
2030    * DOCUMENT ME!
2031    *
2032    * @param e DOCUMENT ME!
2033    */
2034   public void font_actionPerformed(ActionEvent e)
2035   {
2036     new FontChooser(alignPanel);
2037   }
2038
2039
2040   /**
2041    * DOCUMENT ME!
2042    *
2043    * @param e DOCUMENT ME!
2044    */
2045   protected void seqLimit_actionPerformed(ActionEvent e)
2046   {
2047     viewport.setShowJVSuffix(seqLimits.isSelected());
2048
2049     alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel.calculateIdWidth());
2050     alignPanel.paintAlignment(true);
2051   }
2052
2053   public void idRightAlign_actionPerformed(ActionEvent e)
2054   {
2055     viewport.rightAlignIds = idRightAlign.isSelected();
2056     alignPanel.paintAlignment(true);
2057   }
2058
2059
2060
2061   /**
2062    * DOCUMENT ME!
2063    *
2064    * @param e DOCUMENT ME!
2065    */
2066   protected void colourTextMenuItem_actionPerformed(ActionEvent e)
2067   {
2068     viewport.setColourText(colourTextMenuItem.isSelected());
2069     alignPanel.paintAlignment(true);
2070   }
2071
2072   /**
2073    * DOCUMENT ME!
2074    *
2075    * @param e DOCUMENT ME!
2076    */
2077   public void wrapMenuItem_actionPerformed(ActionEvent e)
2078   {
2079     scaleAbove.setVisible(wrapMenuItem.isSelected());
2080     scaleLeft.setVisible(wrapMenuItem.isSelected());
2081     scaleRight.setVisible(wrapMenuItem.isSelected());
2082     viewport.setWrapAlignment(wrapMenuItem.isSelected());
2083     alignPanel.setWrapAlignment(wrapMenuItem.isSelected());
2084   }
2085
2086   public void showAllSeqs_actionPerformed(ActionEvent e)
2087   {
2088     viewport.showAllHiddenSeqs();
2089   }
2090
2091   public void showAllColumns_actionPerformed(ActionEvent e)
2092   {
2093     viewport.showAllHiddenColumns();
2094     repaint();
2095   }
2096
2097   public void hideSelSequences_actionPerformed(ActionEvent e)
2098   {
2099     viewport.hideAllSelectedSeqs();
2100     alignPanel.paintAlignment(true);
2101   }
2102
2103   public void hideSelColumns_actionPerformed(ActionEvent e)
2104   {
2105     viewport.hideSelectedColumns();
2106     alignPanel.paintAlignment(true);
2107   }
2108
2109   public void hiddenMarkers_actionPerformed(ActionEvent e)
2110   {
2111     viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
2112     repaint();
2113   }
2114
2115   /**
2116    * DOCUMENT ME!
2117    *
2118    * @param e DOCUMENT ME!
2119    */
2120   protected void scaleAbove_actionPerformed(ActionEvent e)
2121   {
2122     viewport.setScaleAboveWrapped(scaleAbove.isSelected());
2123     alignPanel.paintAlignment(true);
2124   }
2125
2126   /**
2127    * DOCUMENT ME!
2128    *
2129    * @param e DOCUMENT ME!
2130    */
2131   protected void scaleLeft_actionPerformed(ActionEvent e)
2132   {
2133     viewport.setScaleLeftWrapped(scaleLeft.isSelected());
2134     alignPanel.paintAlignment(true);
2135   }
2136
2137   /**
2138    * DOCUMENT ME!
2139    *
2140    * @param e DOCUMENT ME!
2141    */
2142   protected void scaleRight_actionPerformed(ActionEvent e)
2143   {
2144     viewport.setScaleRightWrapped(scaleRight.isSelected());
2145     alignPanel.paintAlignment(true);
2146   }
2147
2148   /**
2149    * DOCUMENT ME!
2150    *
2151    * @param e DOCUMENT ME!
2152    */
2153   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
2154   {
2155     viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
2156     alignPanel.paintAlignment(true);
2157   }
2158
2159   /**
2160    * DOCUMENT ME!
2161    *
2162    * @param e DOCUMENT ME!
2163    */
2164   public void viewTextMenuItem_actionPerformed(ActionEvent e)
2165   {
2166     viewport.setShowText(viewTextMenuItem.isSelected());
2167     alignPanel.paintAlignment(true);
2168   }
2169
2170   /**
2171    * DOCUMENT ME!
2172    *
2173    * @param e DOCUMENT ME!
2174    */
2175   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
2176   {
2177     viewport.setRenderGaps(renderGapsMenuItem.isSelected());
2178     alignPanel.paintAlignment(true);
2179   }
2180
2181
2182   public FeatureSettings featureSettings;
2183   public void featureSettings_actionPerformed(ActionEvent e)
2184   {
2185     if(featureSettings !=null )
2186     {
2187       featureSettings.close();
2188       featureSettings = null;
2189     }
2190     featureSettings = new FeatureSettings(this);
2191   }
2192
2193   /**
2194    * DOCUMENT ME!
2195    *
2196    * @param evt DOCUMENT ME!
2197    */
2198   public void showSeqFeatures_actionPerformed(ActionEvent evt)
2199   {
2200     viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
2201     alignPanel.paintAlignment(true);
2202     if (alignPanel.getOverviewPanel() != null)
2203     {
2204       alignPanel.getOverviewPanel().updateOverviewImage();
2205     }
2206   }
2207
2208   /**
2209    * DOCUMENT ME!
2210    *
2211    * @param e DOCUMENT ME!
2212    */
2213   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
2214   {
2215     viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());
2216     alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());
2217   }
2218
2219   /**
2220    * DOCUMENT ME!
2221    *
2222    * @param e DOCUMENT ME!
2223    */
2224   public void overviewMenuItem_actionPerformed(ActionEvent e)
2225   {
2226     if (alignPanel.overviewPanel != null)
2227     {
2228       return;
2229     }
2230
2231     JInternalFrame frame = new JInternalFrame();
2232     OverviewPanel overview = new OverviewPanel(alignPanel);
2233     frame.setContentPane(overview);
2234     Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),
2235                              frame.getWidth(), frame.getHeight());
2236     frame.pack();
2237     frame.setLayer(JLayeredPane.PALETTE_LAYER);
2238     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
2239     {
2240       public void internalFrameClosed(
2241           javax.swing.event.InternalFrameEvent evt)
2242       {
2243         alignPanel.setOverviewPanel(null);
2244       }
2245       ;
2246     });
2247
2248     alignPanel.setOverviewPanel(overview);
2249   }
2250
2251   public void textColour_actionPerformed(ActionEvent e)
2252   {
2253     new TextColourChooser().chooseColour(alignPanel, null);
2254   }
2255
2256   /**
2257    * DOCUMENT ME!
2258    *
2259    * @param e DOCUMENT ME!
2260    */
2261   protected void noColourmenuItem_actionPerformed(ActionEvent e)
2262   {
2263     changeColour(null);
2264   }
2265
2266   /**
2267    * DOCUMENT ME!
2268    *
2269    * @param e DOCUMENT ME!
2270    */
2271   public void clustalColour_actionPerformed(ActionEvent e)
2272   {
2273     changeColour(new ClustalxColourScheme(
2274         viewport.alignment.getSequences(), viewport.alignment.getWidth()));
2275   }
2276
2277   /**
2278    * DOCUMENT ME!
2279    *
2280    * @param e DOCUMENT ME!
2281    */
2282   public void zappoColour_actionPerformed(ActionEvent e)
2283   {
2284     changeColour(new ZappoColourScheme());
2285   }
2286
2287   /**
2288    * DOCUMENT ME!
2289    *
2290    * @param e DOCUMENT ME!
2291    */
2292   public void taylorColour_actionPerformed(ActionEvent e)
2293   {
2294     changeColour(new TaylorColourScheme());
2295   }
2296
2297   /**
2298    * DOCUMENT ME!
2299    *
2300    * @param e DOCUMENT ME!
2301    */
2302   public void hydrophobicityColour_actionPerformed(ActionEvent e)
2303   {
2304     changeColour(new HydrophobicColourScheme());
2305   }
2306
2307   /**
2308    * DOCUMENT ME!
2309    *
2310    * @param e DOCUMENT ME!
2311    */
2312   public void helixColour_actionPerformed(ActionEvent e)
2313   {
2314     changeColour(new HelixColourScheme());
2315   }
2316
2317   /**
2318    * DOCUMENT ME!
2319    *
2320    * @param e DOCUMENT ME!
2321    */
2322   public void strandColour_actionPerformed(ActionEvent e)
2323   {
2324     changeColour(new StrandColourScheme());
2325   }
2326
2327   /**
2328    * DOCUMENT ME!
2329    *
2330    * @param e DOCUMENT ME!
2331    */
2332   public void turnColour_actionPerformed(ActionEvent e)
2333   {
2334     changeColour(new TurnColourScheme());
2335   }
2336
2337   /**
2338    * DOCUMENT ME!
2339    *
2340    * @param e DOCUMENT ME!
2341    */
2342   public void buriedColour_actionPerformed(ActionEvent e)
2343   {
2344     changeColour(new BuriedColourScheme());
2345   }
2346
2347   /**
2348    * DOCUMENT ME!
2349    *
2350    * @param e DOCUMENT ME!
2351    */
2352   public void nucleotideColour_actionPerformed(ActionEvent e)
2353   {
2354     changeColour(new NucleotideColourScheme());
2355   }
2356
2357   public void annotationColour_actionPerformed(ActionEvent e)
2358   {
2359     new AnnotationColourChooser(viewport, alignPanel);
2360   }
2361
2362
2363   /**
2364    * DOCUMENT ME!
2365    *
2366    * @param e DOCUMENT ME!
2367    */
2368   protected void applyToAllGroups_actionPerformed(ActionEvent e)
2369   {
2370     viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
2371   }
2372
2373   /**
2374    * DOCUMENT ME!
2375    *
2376    * @param cs DOCUMENT ME!
2377    */
2378   public void changeColour(ColourSchemeI cs)
2379   {
2380     int threshold = 0;
2381
2382     if(cs!=null)
2383     {
2384       if (viewport.getAbovePIDThreshold())
2385       {
2386         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,
2387                                                    "Background");
2388
2389         cs.setThreshold(threshold,
2390                         viewport.getIgnoreGapsConsensus());
2391
2392         viewport.setGlobalColourScheme(cs);
2393       }
2394       else
2395       {
2396         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2397       }
2398
2399       if (viewport.getConservationSelected())
2400       {
2401
2402         Alignment al = (Alignment) viewport.alignment;
2403         Conservation c = new Conservation("All",
2404                                           ResidueProperties.propHash, 3,
2405                                           al.getSequences(), 0,
2406                                           al.getWidth() - 1);
2407
2408         c.calculate();
2409         c.verdict(false, viewport.ConsPercGaps);
2410
2411         cs.setConservation(c);
2412
2413         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,
2414             "Background"));
2415       }
2416       else
2417       {
2418         cs.setConservation(null);
2419       }
2420
2421       cs.setConsensus(viewport.hconsensus);
2422     }
2423
2424     viewport.setGlobalColourScheme(cs);
2425
2426     if (viewport.getColourAppliesToAllGroups())
2427     {
2428       Vector groups = viewport.alignment.getGroups();
2429
2430       for (int i = 0; i < groups.size(); i++)
2431       {
2432         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
2433
2434         if (cs == null)
2435         {
2436           sg.cs = null;
2437           continue;
2438         }
2439
2440         if (cs instanceof ClustalxColourScheme)
2441         {
2442           sg.cs = new ClustalxColourScheme(
2443               sg.getSequences(viewport.hiddenRepSequences), sg.getWidth());
2444         }
2445         else if (cs instanceof UserColourScheme)
2446         {
2447           sg.cs = new UserColourScheme( ( (UserColourScheme) cs).getColours());
2448         }
2449         else
2450         {
2451           try
2452           {
2453             sg.cs = (ColourSchemeI) cs.getClass().newInstance();
2454           }
2455           catch (Exception ex)
2456           {
2457           }
2458         }
2459
2460         if (viewport.getAbovePIDThreshold()
2461             || cs instanceof PIDColourScheme
2462             || cs instanceof Blosum62ColourScheme)
2463         {
2464          sg.cs.setThreshold(threshold,
2465                 viewport.getIgnoreGapsConsensus());
2466
2467          sg.cs.setConsensus(AAFrequency.calculate(
2468              sg.getSequences(viewport.hiddenRepSequences), sg.getStartRes(),
2469              sg.getEndRes()+1));
2470        }
2471         else
2472         {
2473           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2474         }
2475
2476
2477         if (viewport.getConservationSelected())
2478         {
2479           Conservation c = new Conservation("Group",
2480                                             ResidueProperties.propHash, 3,
2481                                             sg.getSequences(viewport.
2482               hiddenRepSequences),
2483                                             sg.getStartRes(),
2484                                             sg.getEndRes()+1);
2485           c.calculate();
2486           c.verdict(false, viewport.ConsPercGaps);
2487           sg.cs.setConservation(c);
2488         }
2489         else
2490         {
2491           sg.cs.setConservation(null);
2492       }
2493     }
2494     }
2495
2496     if (alignPanel.getOverviewPanel() != null)
2497     {
2498       alignPanel.getOverviewPanel().updateOverviewImage();
2499     }
2500
2501
2502
2503
2504     alignPanel.paintAlignment(true);
2505   }
2506
2507   /**
2508    * DOCUMENT ME!
2509    *
2510    * @param e DOCUMENT ME!
2511    */
2512   protected void modifyPID_actionPerformed(ActionEvent e)
2513   {
2514     if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme!=null)
2515     {
2516       SliderPanel.setPIDSliderSource(alignPanel,
2517                                      viewport.getGlobalColourScheme(),
2518                                      "Background");
2519       SliderPanel.showPIDSlider();
2520     }
2521   }
2522
2523   /**
2524    * DOCUMENT ME!
2525    *
2526    * @param e DOCUMENT ME!
2527    */
2528   protected void modifyConservation_actionPerformed(ActionEvent e)
2529   {
2530     if (viewport.getConservationSelected() && viewport.globalColourScheme!=null)
2531     {
2532       SliderPanel.setConservationSlider(alignPanel,
2533                                         viewport.globalColourScheme,
2534                                         "Background");
2535       SliderPanel.showConservationSlider();
2536     }
2537   }
2538
2539   /**
2540    * DOCUMENT ME!
2541    *
2542    * @param e DOCUMENT ME!
2543    */
2544   protected void conservationMenuItem_actionPerformed(ActionEvent e)
2545   {
2546     viewport.setConservationSelected(conservationMenuItem.isSelected());
2547
2548     viewport.setAbovePIDThreshold(false);
2549     abovePIDThreshold.setSelected(false);
2550
2551     changeColour(viewport.getGlobalColourScheme());
2552
2553     modifyConservation_actionPerformed(null);
2554   }
2555
2556   /**
2557    * DOCUMENT ME!
2558    *
2559    * @param e DOCUMENT ME!
2560    */
2561   public void abovePIDThreshold_actionPerformed(ActionEvent e)
2562   {
2563     viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());
2564
2565     conservationMenuItem.setSelected(false);
2566     viewport.setConservationSelected(false);
2567
2568     changeColour(viewport.getGlobalColourScheme());
2569
2570     modifyPID_actionPerformed(null);
2571   }
2572
2573   /**
2574    * DOCUMENT ME!
2575    *
2576    * @param e DOCUMENT ME!
2577    */
2578   public void userDefinedColour_actionPerformed(ActionEvent e)
2579   {
2580     if (e.getActionCommand().equals("User Defined..."))
2581     {
2582       new UserDefinedColours(alignPanel, null);
2583     }
2584     else
2585     {
2586       UserColourScheme udc = (UserColourScheme) UserDefinedColours.
2587           getUserColourSchemes().get(e.getActionCommand());
2588
2589       changeColour(udc);
2590     }
2591   }
2592
2593   public void updateUserColourMenu()
2594   {
2595
2596     Component[] menuItems = colourMenu.getMenuComponents();
2597     int i, iSize = menuItems.length;
2598     for (i = 0; i < iSize; i++)
2599     {
2600       if (menuItems[i].getName() != null &&
2601           menuItems[i].getName().equals("USER_DEFINED"))
2602       {
2603         colourMenu.remove(menuItems[i]);
2604         iSize--;
2605       }
2606     }
2607     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
2608     {
2609       java.util.Enumeration userColours = jalview.gui.UserDefinedColours.
2610           getUserColourSchemes().keys();
2611
2612       while (userColours.hasMoreElements())
2613       {
2614         final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
2615             userColours.
2616             nextElement().toString());
2617         radioItem.setName("USER_DEFINED");
2618         radioItem.addMouseListener(new MouseAdapter()
2619             {
2620               public void mousePressed(MouseEvent evt)
2621               {
2622                 if(evt.isControlDown() || SwingUtilities.isRightMouseButton(evt))
2623                 {
2624                   radioItem.removeActionListener(radioItem.getActionListeners()[0]);
2625
2626               int option = JOptionPane.showInternalConfirmDialog(jalview.gui.
2627                   Desktop.desktop,
2628                       "Remove from default list?",
2629                       "Remove user defined colour",
2630                       JOptionPane.YES_NO_OPTION);
2631                   if(option == JOptionPane.YES_OPTION)
2632                   {
2633                 jalview.gui.UserDefinedColours.removeColourFromDefaults(
2634                     radioItem.getText());
2635                     colourMenu.remove(radioItem);
2636                   }
2637                   else
2638               {
2639                     radioItem.addActionListener(new ActionListener()
2640                     {
2641                       public void actionPerformed(ActionEvent evt)
2642                       {
2643                         userDefinedColour_actionPerformed(evt);
2644                       }
2645                     });
2646                 }
2647               }
2648           }
2649             });
2650         radioItem.addActionListener(new ActionListener()
2651         {
2652           public void actionPerformed(ActionEvent evt)
2653           {
2654             userDefinedColour_actionPerformed(evt);
2655           }
2656         });
2657
2658         colourMenu.insert(radioItem, 15);
2659         colours.add(radioItem);
2660       }
2661     }
2662   }
2663
2664   /**
2665    * DOCUMENT ME!
2666    *
2667    * @param e DOCUMENT ME!
2668    */
2669   public void PIDColour_actionPerformed(ActionEvent e)
2670   {
2671     changeColour(new PIDColourScheme());
2672   }
2673
2674   /**
2675    * DOCUMENT ME!
2676    *
2677    * @param e DOCUMENT ME!
2678    */
2679   public void BLOSUM62Colour_actionPerformed(ActionEvent e)
2680   {
2681     changeColour(new Blosum62ColourScheme());
2682   }
2683
2684   /**
2685    * DOCUMENT ME!
2686    *
2687    * @param e DOCUMENT ME!
2688    */
2689   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
2690   {
2691     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2692     AlignmentSorter.sortByPID(viewport.getAlignment(),
2693                               viewport.getAlignment().getSequenceAt(0));
2694     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
2695                                     viewport.alignment));
2696     alignPanel.paintAlignment(true);
2697   }
2698
2699   /**
2700    * DOCUMENT ME!
2701    *
2702    * @param e DOCUMENT ME!
2703    */
2704   public void sortIDMenuItem_actionPerformed(ActionEvent e)
2705   {
2706     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2707     AlignmentSorter.sortByID(viewport.getAlignment());
2708     addHistoryItem(new OrderCommand("ID Sort", oldOrder, viewport.alignment));
2709     alignPanel.paintAlignment(true);
2710   }
2711
2712   /**
2713    * DOCUMENT ME!
2714    *
2715    * @param e DOCUMENT ME!
2716    */
2717   public void sortGroupMenuItem_actionPerformed(ActionEvent e)
2718   {
2719     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2720     AlignmentSorter.sortByGroup(viewport.getAlignment());
2721     addHistoryItem(new OrderCommand("Group Sort", oldOrder, viewport.alignment));
2722
2723     alignPanel.paintAlignment(true);
2724   }
2725
2726   /**
2727    * DOCUMENT ME!
2728    *
2729    * @param e DOCUMENT ME!
2730    */
2731   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
2732   {
2733     new RedundancyPanel(alignPanel, this);
2734   }
2735
2736
2737   /**
2738    * DOCUMENT ME!
2739    *
2740    * @param e DOCUMENT ME!
2741    */
2742   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
2743   {
2744     if ( (viewport.getSelectionGroup() == null) ||
2745         (viewport.getSelectionGroup().getSize() < 2))
2746     {
2747       JOptionPane.showInternalMessageDialog(this,
2748                                             "You must select at least 2 sequences.",
2749                                             "Invalid Selection",
2750                                             JOptionPane.WARNING_MESSAGE);
2751     }
2752     else
2753     {
2754       JInternalFrame frame = new JInternalFrame();
2755       frame.setContentPane(new PairwiseAlignPanel(viewport));
2756       Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);
2757     }
2758   }
2759
2760   /**
2761    * DOCUMENT ME!
2762    *
2763    * @param e DOCUMENT ME!
2764    */
2765   public void PCAMenuItem_actionPerformed(ActionEvent e)
2766   {
2767     if ( ( (viewport.getSelectionGroup() != null) &&
2768           (viewport.getSelectionGroup().getSize() < 4) &&
2769           (viewport.getSelectionGroup().getSize() > 0)) ||
2770         (viewport.getAlignment().getHeight() < 4))
2771     {
2772       JOptionPane.showInternalMessageDialog(this,
2773                                             "Principal component analysis must take\n" +
2774                                             "at least 4 input sequences.",
2775                                             "Sequence selection insufficient",
2776                                             JOptionPane.WARNING_MESSAGE);
2777
2778       return;
2779     }
2780
2781      new PCAPanel(alignPanel);
2782   }
2783
2784
2785   public void autoCalculate_actionPerformed(ActionEvent e)
2786   {
2787     viewport.autoCalculateConsensus = autoCalculate.isSelected();
2788     if(viewport.autoCalculateConsensus)
2789     {
2790       viewport.firePropertyChange("alignment",
2791                                   null,
2792                                   viewport.getAlignment().getSequences());
2793     }
2794   }
2795
2796
2797   /**
2798    * DOCUMENT ME!
2799    *
2800    * @param e DOCUMENT ME!
2801    */
2802   public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
2803   {
2804     NewTreePanel("AV", "PID", "Average distance tree using PID");
2805   }
2806
2807   /**
2808    * DOCUMENT ME!
2809    *
2810    * @param e DOCUMENT ME!
2811    */
2812   public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
2813   {
2814     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
2815   }
2816
2817   /**
2818    * DOCUMENT ME!
2819    *
2820    * @param e DOCUMENT ME!
2821    */
2822   protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
2823   {
2824     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
2825   }
2826
2827   /**
2828    * DOCUMENT ME!
2829    *
2830    * @param e DOCUMENT ME!
2831    */
2832   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
2833   {
2834     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
2835   }
2836
2837   /**
2838    * DOCUMENT ME!
2839    *
2840    * @param type DOCUMENT ME!
2841    * @param pwType DOCUMENT ME!
2842    * @param title DOCUMENT ME!
2843    */
2844   void NewTreePanel(String type, String pwType, String title)
2845   {
2846     TreePanel tp;
2847
2848     if (viewport.getSelectionGroup() != null)
2849     {
2850       if (viewport.getSelectionGroup().getSize() < 3)
2851       {
2852         JOptionPane.showMessageDialog(Desktop.desktop,
2853                                       "You need to have more than two sequences selected to build a tree!",
2854                                       "Not enough sequences",
2855                                       JOptionPane.WARNING_MESSAGE);
2856         return;
2857       }
2858
2859       int s = 0;
2860       SequenceGroup sg = viewport.getSelectionGroup();
2861
2862       /* Decide if the selection is a column region */
2863       while (s < sg.getSize())
2864       {
2865         if ( ( (SequenceI) sg.getSequences(null).elementAt(s++)).getLength() <
2866             sg.getEndRes())
2867         {
2868           JOptionPane.showMessageDialog(Desktop.desktop,
2869                                         "The selected region to create a tree may\nonly contain residues or gaps.\n" +
2870                                         "Try using the Pad function in the edit menu,\n" +
2871                                         "or one of the multiple sequence alignment web services.",
2872                                         "Sequences in selection are not aligned",
2873                                         JOptionPane.WARNING_MESSAGE);
2874
2875           return;
2876         }
2877       }
2878
2879       title = title + " on region";
2880       tp = new TreePanel(alignPanel, type, pwType);
2881     }
2882     else
2883     {
2884       //are the sequences aligned?
2885       if (!viewport.alignment.isAligned())
2886       {
2887         JOptionPane.showMessageDialog(Desktop.desktop,
2888                                       "The sequences must be aligned before creating a tree.\n" +
2889                                       "Try using the Pad function in the edit menu,\n" +
2890                                       "or one of the multiple sequence alignment web services.",
2891                                       "Sequences not aligned",
2892                                       JOptionPane.WARNING_MESSAGE);
2893
2894         return;
2895       }
2896
2897       if(viewport.alignment.getHeight()<2)
2898       {
2899         return;
2900       }
2901
2902       tp = new TreePanel(alignPanel, type, pwType);
2903     }
2904
2905     title += " from ";
2906
2907     if(viewport.viewName!=null)
2908     {
2909       title+= viewport.viewName+" of ";
2910     }
2911
2912     title += this.title;
2913
2914     Desktop.addInternalFrame(tp, title, 600, 500);
2915   }
2916
2917   /**
2918    * DOCUMENT ME!
2919    *
2920    * @param title DOCUMENT ME!
2921    * @param order DOCUMENT ME!
2922    */
2923   public void addSortByOrderMenuItem(String title, final AlignmentOrder order)
2924   {
2925     final JMenuItem item = new JMenuItem("by " + title);
2926     sort.add(item);
2927     item.addActionListener(new java.awt.event.ActionListener()
2928     {
2929       public void actionPerformed(ActionEvent e)
2930       {
2931         SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2932
2933         // TODO: JBPNote - have to map order entries to curent SequenceI pointers
2934         AlignmentSorter.sortBy(viewport.getAlignment(), order);
2935
2936         addHistoryItem(new OrderCommand(order.getName(), oldOrder,
2937                                         viewport.alignment));
2938
2939         alignPanel.paintAlignment(true);
2940       }
2941     });
2942   }
2943
2944   /**
2945    * Maintain the Order by->Displayed Tree menu.
2946    * Creates a new menu item for a TreePanel with an appropriate
2947    * <code>jalview.analysis.AlignmentSorter</code> call. Listeners are added
2948    * to remove the menu item when the treePanel is closed, and adjust
2949    * the tree leaf to sequence mapping when the alignment is modified.
2950    * @param treePanel Displayed tree window.
2951    * @param title SortBy menu item title.
2952    */
2953   public void buildTreeMenu()
2954   {
2955     sortByTreeMenu.removeAll();
2956
2957     Vector comps = (Vector) PaintRefresher.components.get(viewport.
2958         getSequenceSetId());
2959     Vector treePanels = new Vector();
2960     int i, iSize = comps.size();
2961     for(i=0; i<iSize; i++)
2962     {
2963       if(comps.elementAt(i) instanceof TreePanel)
2964       {
2965         treePanels.add(comps.elementAt(i));
2966       }
2967     }
2968
2969     iSize = treePanels.size();
2970
2971     if(iSize<1)
2972     {
2973       sortByTreeMenu.setVisible(false);
2974       return;
2975     }
2976
2977     sortByTreeMenu.setVisible(true);
2978
2979     for(i=0; i<treePanels.size(); i++)
2980     {
2981       TreePanel tp = (TreePanel)treePanels.elementAt(i);
2982       final JMenuItem item = new JMenuItem(tp.getTitle());
2983       final NJTree tree = ((TreePanel)treePanels.elementAt(i)).getTree();
2984       item.addActionListener(new java.awt.event.ActionListener()
2985       {
2986         public void actionPerformed(ActionEvent e)
2987         {
2988           SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2989           AlignmentSorter.sortByTree(viewport.getAlignment(), tree);
2990
2991           addHistoryItem(new OrderCommand("Tree Sort",
2992                                           oldOrder,
2993                                           viewport.alignment));
2994
2995           alignPanel.paintAlignment(true);
2996         }
2997       });
2998
2999       sortByTreeMenu.add(item);
3000     }
3001   }
3002
3003   /**
3004    * Work out whether the whole set of sequences
3005    * or just the selected set will be submitted for multiple alignment.
3006    *
3007    */
3008   private jalview.datamodel.AlignmentView gatherSequencesForAlignment()
3009   {
3010     // Now, check we have enough sequences
3011     AlignmentView msa = null;
3012
3013     if ( (viewport.getSelectionGroup() != null) &&
3014         (viewport.getSelectionGroup().getSize() > 1))
3015     {
3016       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
3017       /*SequenceGroup seqs = viewport.getSelectionGroup();
3018       int sz;
3019       msa = new SequenceI[sz = seqs.getSize(false)];
3020
3021       for (int i = 0; i < sz; i++)
3022       {
3023         msa[i] = (SequenceI) seqs.getSequenceAt(i);
3024       } */
3025       msa = viewport.getAlignmentView(true);
3026     }
3027     else
3028     {
3029       /*Vector seqs = viewport.getAlignment().getSequences();
3030
3031       if (seqs.size() > 1)
3032       {
3033         msa = new SequenceI[seqs.size()];
3034
3035         for (int i = 0; i < seqs.size(); i++)
3036         {
3037           msa[i] = (SequenceI) seqs.elementAt(i);
3038         }
3039       }*/
3040       msa = viewport.getAlignmentView(false);
3041     }
3042     return msa;
3043   }
3044
3045   /**
3046    * Decides what is submitted to a secondary structure prediction service,
3047    * the currently selected sequence, or the currently selected alignment
3048    * (where the first sequence in the set is the one that the prediction
3049    * will be for).
3050    */
3051   AlignmentView gatherSeqOrMsaForSecStrPrediction()
3052   {
3053    AlignmentView seqs = null;
3054
3055     if ( (viewport.getSelectionGroup() != null) &&
3056         (viewport.getSelectionGroup().getSize() > 0))
3057     {
3058       seqs = viewport.getAlignmentView(true);
3059     }
3060     else
3061     {
3062       seqs = viewport.getAlignmentView(false);
3063     }
3064     // limit sequences - JBPNote in future - could spawn multiple prediction jobs
3065     // TODO: viewport.alignment.isAligned is a global state - the local selection may well be aligned - we preserve 2.0.8 behaviour for moment.
3066     if (!viewport.alignment.isAligned())
3067     {
3068       seqs.setSequences(new SeqCigar[]
3069                         {seqs.getSequences()[0]});
3070     }
3071     return seqs;
3072   }
3073   /**
3074    * DOCUMENT ME!
3075    *
3076    * @param e DOCUMENT ME!
3077    */
3078   protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)
3079   {
3080     // Pick the tree file
3081     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
3082         getProperty(
3083             "LAST_DIRECTORY"));
3084     chooser.setFileView(new JalviewFileView());
3085     chooser.setDialogTitle("Select a newick-like tree file");
3086     chooser.setToolTipText("Load a tree file");
3087
3088     int value = chooser.showOpenDialog(null);
3089
3090     if (value == JalviewFileChooser.APPROVE_OPTION)
3091     {
3092       String choice = chooser.getSelectedFile().getPath();
3093       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
3094
3095       try
3096       {
3097         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,
3098             "File");
3099         viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
3100       }
3101       catch (Exception ex)
3102       {
3103         JOptionPane.showMessageDialog(Desktop.desktop,
3104                                       "Problem reading tree file",
3105                                       ex.getMessage(),
3106                                       JOptionPane.WARNING_MESSAGE);
3107         ex.printStackTrace();
3108       }
3109     }
3110   }
3111
3112
3113   public TreePanel ShowNewickTree(NewickFile nf, String title)
3114   {
3115     return ShowNewickTree(nf,title,600,500,4,5);
3116   }
3117
3118   public TreePanel ShowNewickTree(NewickFile nf, String title,
3119                                   AlignmentView input)
3120   {
3121     return ShowNewickTree(nf,title, input, 600,500,4,5);
3122   }
3123
3124   public TreePanel ShowNewickTree(NewickFile nf, String title, int w, int h,
3125                                   int x, int y)
3126   {
3127     return ShowNewickTree(nf, title, null, w, h, x, y);
3128   }
3129   /**
3130    * Add a treeviewer for the tree extracted from a newick file object to the current alignment view
3131    *
3132    * @param nf the tree
3133    * @param title tree viewer title
3134    * @param input Associated alignment input data (or null)
3135    * @param w width
3136    * @param h height
3137    * @param x position
3138    * @param y position
3139    * @return TreePanel handle
3140    */
3141   public TreePanel ShowNewickTree(NewickFile nf, String title,
3142                                   AlignmentView input, int w, int h, int x,
3143                                   int y)
3144   {
3145     TreePanel tp = null;
3146
3147     try
3148     {
3149       nf.parse();
3150
3151       if (nf.getTree() != null)
3152       {
3153         tp = new TreePanel(alignPanel,
3154                            "FromFile",
3155                            title,
3156                            nf, input);
3157
3158         tp.setSize(w,h);
3159
3160         if(x>0 && y>0)
3161         {
3162           tp.setLocation(x,y);
3163         }
3164
3165
3166         Desktop.addInternalFrame(tp, title, w, h);
3167       }
3168     }
3169     catch (Exception ex)
3170     {
3171       ex.printStackTrace();
3172     }
3173
3174     return tp;
3175   }
3176
3177
3178   /**
3179    * Generates menu items and listener event actions for web service clients
3180    *
3181    */
3182   public void BuildWebServiceMenu()
3183   {
3184     if ( (Discoverer.services != null)
3185         && (Discoverer.services.size() > 0))
3186     {
3187       Vector msaws = (Vector) Discoverer.services.get("MsaWS");
3188       Vector secstrpr = (Vector) Discoverer.services.get("SecStrPred");
3189       Vector wsmenu = new Vector();
3190       final AlignFrame af = this;
3191       if (msaws != null)
3192       {
3193         // Add any Multiple Sequence Alignment Services
3194         final JMenu msawsmenu = new JMenu("Alignment");
3195         for (int i = 0, j = msaws.size(); i < j; i++)
3196         {
3197           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.
3198               get(i);
3199           final JMenuItem method = new JMenuItem(sh.getName());
3200           method.addActionListener(new ActionListener()
3201           {
3202             public void actionPerformed(ActionEvent e)
3203             {
3204               AlignmentView msa = gatherSequencesForAlignment();
3205               new jalview.ws.MsaWSClient(sh, title, msa,
3206                                          false, true,
3207                                          viewport.getAlignment().getDataset(),
3208                                          af);
3209
3210             }
3211
3212           });
3213           msawsmenu.add(method);
3214           // Deal with services that we know accept partial alignments.
3215           if (sh.getName().indexOf("lustal") > -1)
3216           {
3217             // We know that ClustalWS can accept partial alignments for refinement.
3218             final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");
3219             methodR.addActionListener(new ActionListener()
3220             {
3221               public void actionPerformed(ActionEvent e)
3222               {
3223                 AlignmentView msa = gatherSequencesForAlignment();
3224                 new jalview.ws.MsaWSClient(sh, title, msa,
3225                                            true, true,
3226                                            viewport.getAlignment().getDataset(),
3227                                            af);
3228
3229               }
3230
3231             });
3232             msawsmenu.add(methodR);
3233
3234           }
3235         }
3236         wsmenu.add(msawsmenu);
3237       }
3238       if (secstrpr != null)
3239       {
3240         // Add any secondary structure prediction services
3241         final JMenu secstrmenu = new JMenu("Secondary Structure Prediction");
3242         for (int i = 0, j = secstrpr.size(); i < j; i++)
3243         {
3244           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)
3245               secstrpr.get(i);
3246           final JMenuItem method = new JMenuItem(sh.getName());
3247           method.addActionListener(new ActionListener()
3248           {
3249             public void actionPerformed(ActionEvent e)
3250             {
3251               AlignmentView msa = gatherSeqOrMsaForSecStrPrediction();
3252               if (msa.getSequences().length == 1)
3253               {
3254                 // Single Sequence prediction
3255                 new jalview.ws.JPredClient(sh, title, false, msa, af, true);
3256               }
3257               else
3258               {
3259                 if (msa.getSequences().length > 1)
3260                 {
3261                   // Sequence profile based prediction
3262                   new jalview.ws.JPredClient(sh,
3263                       title, true, msa, af, true);
3264                 }
3265               }
3266             }
3267           });
3268           secstrmenu.add(method);
3269         }
3270         wsmenu.add(secstrmenu);
3271       }
3272       this.webService.removeAll();
3273       for (int i = 0, j = wsmenu.size(); i < j; i++)
3274       {
3275         webService.add( (JMenu) wsmenu.get(i));
3276       }
3277     }
3278     else
3279     {
3280       this.webService.removeAll();
3281       this.webService.add(this.webServiceNoServices);
3282     }
3283     // TODO: add in rediscovery function
3284     // TODO: reduce code redundancy.
3285     // TODO: group services by location as well as function.
3286   }
3287
3288  /* public void vamsasStore_actionPerformed(ActionEvent e)
3289   {
3290     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
3291         getProperty("LAST_DIRECTORY"));
3292
3293     chooser.setFileView(new JalviewFileView());
3294     chooser.setDialogTitle("Export to Vamsas file");
3295     chooser.setToolTipText("Export");
3296
3297     int value = chooser.showSaveDialog(this);
3298
3299     if (value == JalviewFileChooser.APPROVE_OPTION)
3300     {
3301       jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);
3302       //vs.store(chooser.getSelectedFile().getAbsolutePath()   );
3303       vs.storeJalview( chooser.getSelectedFile().getAbsolutePath(), this);
3304     }
3305   }*/
3306
3307
3308
3309
3310 public void showTranslation_actionPerformed(ActionEvent e)
3311 {
3312   ///////////////////////////////
3313   // Collect Data to be translated/transferred
3314
3315   SequenceI [] selection = viewport.getSelectionAsNewSequence();
3316   String [] seqstring = viewport.getViewAsString(true);
3317   AlignmentI al  = null;
3318   try {
3319     al = jalview.analysis.Dna.CdnaTranslate(selection, seqstring, viewport.getViewAsVisibleContigs(true),
3320         viewport.getGapCharacter(), viewport.alignment.getAlignmentAnnotation(),
3321         viewport.alignment.getWidth());
3322   } catch (Exception ex) {
3323     al = null;
3324     jalview.bin.Cache.log.debug("Exception during translation.",ex);
3325   }
3326   if (al==null)
3327   {
3328     JOptionPane.showMessageDialog(Desktop.desktop,
3329         "Please select at least three bases in at least one sequence in order to perform a cDNA translation.",
3330         "Translation Failed",
3331         JOptionPane.WARNING_MESSAGE);
3332   } else {
3333     AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
3334     Desktop.addInternalFrame(af, "Translation of "+this.getTitle(),
3335                              DEFAULT_WIDTH,
3336                              DEFAULT_HEIGHT);
3337   }
3338 }
3339
3340 /**
3341  * DOCUMENT ME!
3342  *
3343  * @param String DOCUMENT ME!
3344  */
3345 public boolean parseFeaturesFile(String file, String type)
3346 {
3347     boolean featuresFile = false;
3348     try
3349     {
3350       featuresFile = new FeaturesFile(file,
3351           type).parse(viewport.alignment.getDataset(),
3352                                          alignPanel.seqPanel.seqCanvas.
3353                                          getFeatureRenderer().featureColours,
3354                                          false);
3355     }
3356     catch(Exception ex)
3357     {
3358       ex.printStackTrace();
3359     }
3360
3361     if(featuresFile)
3362     {
3363       viewport.showSequenceFeatures = true;
3364       showSeqFeatures.setSelected(true);
3365       alignPanel.paintAlignment(true);
3366     }
3367
3368     return featuresFile;
3369 }
3370
3371 public void dragEnter(DropTargetDragEvent evt)
3372 {}
3373
3374 public void dragExit(DropTargetEvent evt)
3375 {}
3376
3377 public void dragOver(DropTargetDragEvent evt)
3378 {}
3379
3380 public void dropActionChanged(DropTargetDragEvent evt)
3381 {}
3382
3383 public void drop(DropTargetDropEvent evt)
3384 {
3385     Transferable t = evt.getTransferable();
3386     java.util.List files = null;
3387
3388     try
3389     {
3390       DataFlavor uriListFlavor = new DataFlavor(
3391           "text/uri-list;class=java.lang.String");
3392       if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3393       {
3394         //Works on Windows and MacOSX
3395         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3396         files = (java.util.List) t.getTransferData(DataFlavor.
3397             javaFileListFlavor);
3398       }
3399       else if (t.isDataFlavorSupported(uriListFlavor))
3400       {
3401         // This is used by Unix drag system
3402         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3403         String data = (String) t.getTransferData(uriListFlavor);
3404         files = new java.util.ArrayList(1);
3405         for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3406             data,
3407             "\r\n");
3408              st.hasMoreTokens(); )
3409         {
3410           String s = st.nextToken();
3411           if (s.startsWith("#"))
3412           {
3413             // the line is a comment (as per the RFC 2483)
3414             continue;
3415           }
3416
3417           java.net.URI uri = new java.net.URI(s);
3418           java.io.File file = new java.io.File(uri);
3419           files.add(file);
3420         }
3421       }
3422     }
3423     catch (Exception e)
3424     {
3425       e.printStackTrace();
3426     }
3427     if (files != null)
3428     {
3429       try
3430       {
3431
3432         for (int i = 0; i < files.size(); i++)
3433         {
3434           loadJalviewDataFile(files.get(i).toString());
3435         }
3436       }
3437       catch (Exception ex)
3438       {
3439         ex.printStackTrace();
3440       }
3441     }
3442 }
3443
3444   // This method will attempt to load a "dropped" file first by testing
3445   // whether its and Annotation file, then features file. If both are
3446   // false then the user may have dropped an alignment file onto this
3447   // AlignFrame
3448    public void loadJalviewDataFile(String file)
3449   {
3450     try
3451     {
3452       String protocol = "File";
3453
3454       if (file.indexOf("http:") > -1 || file.indexOf("file:") > -1)
3455       {
3456         protocol = "URL";
3457       }
3458
3459       boolean isAnnotation = new AnnotationFile().readAnnotationFile(viewport.
3460           alignment, file, protocol);
3461
3462       if (!isAnnotation)
3463       {
3464         boolean isGroupsFile = parseFeaturesFile(file,protocol);
3465         if (!isGroupsFile)
3466         {
3467           String format = new IdentifyFile().Identify(file, protocol);
3468
3469           if(format.equalsIgnoreCase("JnetFile"))
3470           {
3471             jalview.io.JPredFile predictions = new jalview.io.JPredFile(
3472                 file, protocol);
3473             new JnetAnnotationMaker().add_annotation(predictions,
3474                 viewport.getAlignment(),
3475                 0, false);
3476             alignPanel.adjustAnnotationHeight();
3477             alignPanel.paintAlignment(true);
3478           }
3479           else
3480           {
3481             new FileLoader().LoadFile(viewport, file, protocol, format);
3482         }
3483       }
3484       }
3485       else
3486       {
3487         // (isAnnotation)
3488         alignPanel.adjustAnnotationHeight();
3489       }
3490
3491     }
3492     catch (Exception ex)
3493     {
3494       ex.printStackTrace();
3495     }
3496   }
3497
3498   public void tabSelectionChanged(int index)
3499   {
3500     if (index > -1)
3501     {
3502       alignPanel = (AlignmentPanel) alignPanels.elementAt(index);
3503       viewport = alignPanel.av;
3504       setMenusFromViewport(viewport);
3505     }
3506   }
3507
3508   public void tabbedPane_mousePressed(MouseEvent e)
3509   {
3510     if(SwingUtilities.isRightMouseButton(e))
3511     {
3512       String reply = JOptionPane.showInternalInputDialog(this,
3513           "Enter View Name",
3514           "Edit View Name",
3515           JOptionPane.QUESTION_MESSAGE);
3516
3517       if (reply != null)
3518       {
3519         viewport.viewName = reply;
3520         tabbedPane.setTitleAt( tabbedPane.getSelectedIndex() ,reply);
3521       }
3522     }
3523   }
3524
3525
3526   public AlignViewport getCurrentView()
3527   {
3528     return viewport;
3529   }
3530 }
3531
3532 class PrintThread
3533     extends Thread
3534 {
3535   AlignmentPanel ap;
3536   public PrintThread(AlignmentPanel ap)
3537   {
3538    this.ap = ap;
3539   }
3540   static PageFormat pf;
3541   public void run()
3542   {
3543     PrinterJob printJob = PrinterJob.getPrinterJob();
3544
3545     if (pf != null)
3546     {
3547       printJob.setPrintable(ap, pf);
3548     }
3549     else
3550     {
3551       printJob.setPrintable(ap);
3552     }
3553
3554     if (printJob.printDialog())
3555     {
3556       try
3557       {
3558         printJob.print();
3559       }
3560       catch (Exception PrintException)
3561       {
3562         PrintException.printStackTrace();
3563       }
3564     }
3565   }
3566 }