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