destroy destroyed
[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             jalview.structure.StructureSelectionManager.getStructureSelectionManager()
961                 .removeStructureViewerListener(ap.seqPanel, null);
962             PaintRefresher.RemoveComponent(ap.seqPanel.seqCanvas);
963             PaintRefresher.RemoveComponent(ap.idPanel.idCanvas);
964             PaintRefresher.RemoveComponent(ap);
965           }
966         }
967         else
968         {
969           int index = tabbedPane.getSelectedIndex();
970
971           alignPanels.removeElement(alignPanel);
972           PaintRefresher.RemoveComponent(alignPanel.seqPanel.seqCanvas);
973           PaintRefresher.RemoveComponent(alignPanel.idPanel.idCanvas);
974           PaintRefresher.RemoveComponent(alignPanel);
975           alignPanel.av.alignment.destroyAlignment();
976           alignPanel = null;
977           viewport = null;
978
979           tabbedPane.removeTabAt(index);
980           tabbedPane.validate();
981
982           if(index==tabbedPane.getTabCount())
983           {
984             index --;
985           }
986
987           this.tabSelectionChanged(index);
988         }
989       }
990
991       if (closeAllTabs)
992       {
993         this.setClosed(true);
994     }
995     }
996     catch (Exception ex)
997     {
998       ex.printStackTrace();
999     }
1000   }
1001
1002
1003   /**
1004    * DOCUMENT ME!
1005    */
1006   void updateEditMenuBar()
1007   {
1008
1009     if (viewport.historyList.size() > 0)
1010     {
1011       undoMenuItem.setEnabled(true);
1012       CommandI command = (CommandI) viewport.historyList.peek();
1013       undoMenuItem.setText("Undo " + command.getDescription());
1014     }
1015     else
1016     {
1017       undoMenuItem.setEnabled(false);
1018       undoMenuItem.setText("Undo");
1019     }
1020
1021     if (viewport.redoList.size() > 0)
1022     {
1023       redoMenuItem.setEnabled(true);
1024
1025       CommandI command = (CommandI) viewport.redoList.peek();
1026       redoMenuItem.setText("Redo " + command.getDescription());
1027     }
1028     else
1029     {
1030       redoMenuItem.setEnabled(false);
1031       redoMenuItem.setText("Redo");
1032     }
1033   }
1034
1035
1036   public void addHistoryItem(CommandI command)
1037   {
1038     if(command.getSize()>0)
1039     {
1040       viewport.historyList.push(command);
1041       viewport.redoList.clear();
1042       updateEditMenuBar();
1043       viewport.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
1044     }
1045   }
1046
1047
1048
1049   /**
1050    * DOCUMENT ME!
1051    *
1052    * @param e DOCUMENT ME!
1053    */
1054   protected void undoMenuItem_actionPerformed(ActionEvent e)
1055   {
1056     CommandI command = (CommandI)viewport.historyList.pop();
1057     viewport.redoList.push(command);
1058     command.undoCommand();
1059
1060     AlignViewport originalSource = getOriginatingSource(command);
1061     updateEditMenuBar();
1062
1063     if(originalSource!=null)
1064     {
1065       originalSource.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
1066       originalSource.firePropertyChange("alignment",
1067                                         null,
1068                                         originalSource.alignment.getSequences());
1069     }
1070   }
1071
1072   /**
1073    * DOCUMENT ME!
1074    *
1075    * @param e DOCUMENT ME!
1076    */
1077   protected void redoMenuItem_actionPerformed(ActionEvent e)
1078   {
1079     if(viewport.redoList.size()<1)
1080     {
1081       return;
1082     }
1083
1084     CommandI command = (CommandI) viewport.redoList.pop();
1085     viewport.historyList.push(command);
1086     command.doCommand();
1087
1088     AlignViewport originalSource = getOriginatingSource(command);
1089     updateEditMenuBar();
1090
1091     if(originalSource!=null)
1092     {
1093       originalSource.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
1094       originalSource.firePropertyChange("alignment",
1095                                         null,
1096                                         originalSource.alignment.getSequences());
1097     }
1098   }
1099
1100   AlignViewport getOriginatingSource(CommandI command)
1101   {
1102     AlignViewport originalSource = null;
1103     //For sequence removal and addition, we need to fire
1104    //the property change event FROM the viewport where the
1105    //original alignment was altered
1106     AlignmentI al=null;
1107     if (command instanceof EditCommand)
1108     {
1109       EditCommand editCommand = (EditCommand) command;
1110       al = editCommand.getAlignment();
1111       Vector comps = (Vector) PaintRefresher.components
1112           .get(viewport.getSequenceSetId());
1113
1114       for (int i = 0; i < comps.size(); i++)
1115       {
1116         if (comps.elementAt(i) instanceof AlignmentPanel)
1117         {
1118           if (al == ( (AlignmentPanel) comps.elementAt(i)).av.alignment)
1119           {
1120             originalSource = ( (AlignmentPanel) comps.elementAt(i)).av;
1121             break;
1122           }
1123         }
1124       }
1125     }
1126
1127     if (originalSource == null)
1128     {
1129       //The original view is closed, we must validate
1130       //the current view against the closed view first
1131       if (al != null)
1132       {
1133         PaintRefresher.validateSequences(al, viewport.alignment);
1134       }
1135
1136       originalSource = viewport;
1137     }
1138
1139     return originalSource;
1140   }
1141
1142   /**
1143    * DOCUMENT ME!
1144    *
1145    * @param up DOCUMENT ME!
1146    */
1147   public void moveSelectedSequences(boolean up)
1148   {
1149     SequenceGroup sg = viewport.getSelectionGroup();
1150
1151     if (sg == null)
1152     {
1153       return;
1154     }
1155
1156     if (up)
1157     {
1158       for (int i = 1; i < viewport.alignment.getHeight(); i++)
1159       {
1160         SequenceI seq = viewport.alignment.getSequenceAt(i);
1161
1162         if (!sg.getSequences(null).contains(seq))
1163         {
1164           continue;
1165         }
1166
1167         SequenceI temp = viewport.alignment.getSequenceAt(i - 1);
1168
1169         if (sg.getSequences(null).contains(temp))
1170         {
1171           continue;
1172         }
1173
1174         viewport.alignment.getSequences().setElementAt(temp, i);
1175         viewport.alignment.getSequences().setElementAt(seq, i - 1);
1176       }
1177     }
1178     else
1179     {
1180       for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)
1181       {
1182         SequenceI seq = viewport.alignment.getSequenceAt(i);
1183
1184         if (!sg.getSequences(null).contains(seq))
1185         {
1186           continue;
1187         }
1188
1189         SequenceI temp = viewport.alignment.getSequenceAt(i + 1);
1190
1191         if (sg.getSequences(null).contains(temp))
1192         {
1193           continue;
1194         }
1195
1196         viewport.alignment.getSequences().setElementAt(temp, i);
1197         viewport.alignment.getSequences().setElementAt(seq, i + 1);
1198       }
1199     }
1200
1201     alignPanel.paintAlignment(true);
1202   }
1203
1204
1205
1206
1207   synchronized void slideSequences(boolean right, int size)
1208   {
1209     Vector sg = new Vector();
1210     if(viewport.cursorMode)
1211     {
1212       sg.addElement(viewport.alignment.getSequenceAt(
1213           alignPanel.seqPanel.seqCanvas.cursorY));
1214     }
1215     else if(viewport.getSelectionGroup()!=null
1216         && viewport.getSelectionGroup().getSize()!=viewport.alignment.getHeight())
1217    {
1218      sg = viewport.getSelectionGroup().getSequences(
1219          viewport.hiddenRepSequences);
1220    }
1221
1222     if(sg.size()<1)
1223     {
1224       return;
1225     }
1226
1227     Vector invertGroup = new Vector();
1228
1229     for (int i = 0; i < viewport.alignment.getHeight(); i++)
1230     {
1231       if(!sg.contains(viewport.alignment.getSequenceAt(i)))
1232          invertGroup.add(viewport.alignment.getSequenceAt(i));
1233     }
1234
1235     SequenceI[] seqs1 = new SequenceI[sg.size()];
1236     for (int i = 0; i < sg.size(); i++)
1237       seqs1[i] = (SequenceI) sg.elementAt(i);
1238
1239     SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
1240     for (int i = 0; i < invertGroup.size(); i++)
1241       seqs2[i] = (SequenceI) invertGroup.elementAt(i);
1242
1243     SlideSequencesCommand ssc;
1244     if (right)
1245       ssc = new SlideSequencesCommand("Slide Sequences",
1246                                       seqs2, seqs1, size,
1247                                       viewport.getGapCharacter()
1248           );
1249     else
1250       ssc = new SlideSequencesCommand("Slide Sequences",
1251                                       seqs1, seqs2, size,
1252                                       viewport.getGapCharacter()
1253           );
1254
1255     int groupAdjustment = 0;
1256     if (ssc.getGapsInsertedBegin() && right)
1257     {
1258       if (viewport.cursorMode)
1259         alignPanel.seqPanel.moveCursor(size, 0);
1260       else
1261         groupAdjustment = size;
1262     }
1263     else if (!ssc.getGapsInsertedBegin() && !right)
1264     {
1265       if (viewport.cursorMode)
1266         alignPanel.seqPanel.moveCursor( -size, 0);
1267       else
1268         groupAdjustment = -size;
1269     }
1270
1271     if (groupAdjustment != 0)
1272     {
1273       viewport.getSelectionGroup().setStartRes(
1274           viewport.getSelectionGroup().getStartRes() + groupAdjustment);
1275       viewport.getSelectionGroup().setEndRes(
1276           viewport.getSelectionGroup().getEndRes() + groupAdjustment);
1277     }
1278
1279
1280     boolean appendHistoryItem = false;
1281     if(viewport.historyList!=null
1282        && viewport.historyList.size()>0
1283       && viewport.historyList.peek() instanceof SlideSequencesCommand)
1284     {
1285       appendHistoryItem = ssc.appendSlideCommand(
1286           (SlideSequencesCommand)viewport.historyList.peek())
1287           ;
1288     }
1289
1290     if(!appendHistoryItem)
1291       addHistoryItem(ssc);
1292
1293     repaint();
1294   }
1295
1296
1297   /**
1298    * DOCUMENT ME!
1299    *
1300    * @param e DOCUMENT ME!
1301    */
1302   protected void copy_actionPerformed(ActionEvent e)
1303   {
1304     System.gc();
1305     if (viewport.getSelectionGroup() == null)
1306     {
1307       return;
1308     }
1309
1310     SequenceI [] seqs = viewport.getSelectionAsNewSequence();
1311     String[] omitHidden = null;
1312
1313     if (viewport.hasHiddenColumns)
1314     {
1315       omitHidden = viewport.getViewAsString(true);
1316     }
1317
1318     String output = new FormatAdapter().formatSequences(
1319         "Fasta",
1320         seqs,
1321         omitHidden);
1322
1323     StringSelection ss = new StringSelection(output);
1324
1325     try
1326     {
1327       jalview.gui.Desktop.internalCopy = true;
1328       //Its really worth setting the clipboard contents
1329       //to empty before setting the large StringSelection!!
1330       Toolkit.getDefaultToolkit().getSystemClipboard()
1331           .setContents(new StringSelection(""), null);
1332
1333       Toolkit.getDefaultToolkit().getSystemClipboard()
1334           .setContents(ss, Desktop.instance);
1335     }
1336     catch (OutOfMemoryError er)
1337     {
1338       er.printStackTrace();
1339       javax.swing.SwingUtilities.invokeLater(new Runnable()
1340           {
1341             public void run()
1342             {
1343               javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
1344                   "Out of memory copying region!!"
1345                   +
1346                   "\nSee help files for increasing Java Virtual Machine memory."
1347                   , "Out of memory",
1348                   javax.swing.JOptionPane.WARNING_MESSAGE);
1349             }
1350           });
1351
1352       return;
1353     }
1354
1355     Vector hiddenColumns = null;
1356     if(viewport.hasHiddenColumns)
1357     {
1358       hiddenColumns =new Vector();
1359       int hiddenOffset = viewport.getSelectionGroup().getStartRes();
1360       for (int i = 0; i < viewport.getColumnSelection().getHiddenColumns().size();
1361            i++)
1362       {
1363         int[] region = (int[])
1364             viewport.getColumnSelection().getHiddenColumns().elementAt(i);
1365
1366         hiddenColumns.addElement(new int[]
1367                                  {region[0] - hiddenOffset,
1368                           region[1]-hiddenOffset});
1369       }
1370     }
1371
1372     Desktop.jalviewClipboard = new Object[]
1373         {
1374         seqs,
1375         viewport.alignment.getDataset(),
1376         hiddenColumns};
1377     statusBar.setText("Copied "+seqs.length+" sequences to clipboard.");
1378   }
1379
1380   /**
1381    * DOCUMENT ME!
1382    *
1383    * @param e DOCUMENT ME!
1384    */
1385   protected void pasteNew_actionPerformed(ActionEvent e)
1386   {
1387     paste(true);
1388   }
1389
1390   /**
1391    * DOCUMENT ME!
1392    *
1393    * @param e DOCUMENT ME!
1394    */
1395   protected void pasteThis_actionPerformed(ActionEvent e)
1396   {
1397     paste(false);
1398   }
1399
1400   /**
1401    * DOCUMENT ME!
1402    *
1403    * @param newAlignment DOCUMENT ME!
1404    */
1405   void paste(boolean newAlignment)
1406   {
1407     try
1408     {
1409       Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
1410       Transferable contents = c.getContents(this);
1411
1412       if (contents == null)
1413       {
1414         return;
1415       }
1416
1417       String str, format;
1418       try
1419       {
1420         str = (String) contents.getTransferData(DataFlavor.stringFlavor);
1421         if (str.length() < 1)
1422         {
1423           return;
1424         }
1425
1426         format = new IdentifyFile().Identify(str, "Paste");
1427
1428       }
1429       catch (OutOfMemoryError er)
1430       {
1431         er.printStackTrace();
1432         javax.swing.SwingUtilities.invokeLater(new Runnable()
1433         {
1434           public void run()
1435           {
1436             javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
1437                 "Out of memory pasting sequences!!"
1438                 +
1439                 "\nSee help files for increasing Java Virtual Machine memory."
1440                 , "Out of memory",
1441                 javax.swing.JOptionPane.WARNING_MESSAGE);
1442           }
1443         });
1444
1445         return;
1446       }
1447
1448       SequenceI[] sequences;
1449
1450
1451      if(Desktop.jalviewClipboard!=null)
1452      {
1453        // The clipboard was filled from within Jalview, we must use the sequences
1454        // And dataset from the copied alignment
1455        sequences = (SequenceI[])Desktop.jalviewClipboard[0];
1456      }
1457      else
1458      {
1459         sequences = new FormatAdapter().readFile(str, "Paste", format).
1460             getSequencesArray();
1461      }
1462
1463      AlignmentI alignment = null;
1464
1465       if (newAlignment)
1466       {
1467           alignment = new Alignment(sequences);
1468
1469           if (Desktop.jalviewClipboard != null)
1470         {
1471             alignment.setDataset( (Alignment) Desktop.jalviewClipboard[1]);
1472         }
1473           else
1474         {
1475             alignment.setDataset(null);
1476       }
1477       }
1478       else
1479       {
1480         alignment = viewport.getAlignment();
1481
1482         //!newAlignment
1483         SequenceI [] newseqs = new SequenceI[sequences.length];
1484         for (int i = 0; i < sequences.length; i++)
1485         {
1486           newseqs[i] = new Sequence(sequences[i].getName(),
1487                                     sequences[i].getSequence(),
1488                                     sequences[i].getStart(),
1489               sequences[i].getEnd());
1490
1491           alignment.addSequence(newseqs[i]);
1492         }
1493
1494         /*
1495          //ADD HISTORY ITEM
1496          */
1497         addHistoryItem(new EditCommand(
1498             "Add sequences",
1499             EditCommand.PASTE,
1500             newseqs,
1501             0,
1502             alignment.getWidth(),
1503             alignment)
1504             );
1505
1506
1507         viewport.setEndSeq(alignment.getHeight());
1508         alignment.getWidth();
1509         viewport.firePropertyChange("alignment", null, alignment.getSequences());
1510       }
1511
1512
1513
1514       // Add any annotations attached to sequences
1515       for (int i = 0; i < sequences.length; i++)
1516      {
1517        if (sequences[i].getAnnotation() != null)
1518        {
1519          for (int a = 0; a < sequences[i].getAnnotation().length; a++)
1520          {
1521            AlignmentAnnotation newAnnot =
1522                new AlignmentAnnotation(
1523                    sequences[i].getAnnotation()[a].label,
1524                    sequences[i].getAnnotation()[a].description,
1525                    sequences[i].getAnnotation()[a].annotations,
1526                    sequences[i].getAnnotation()[a].graphMin,
1527                    sequences[i].getAnnotation()[a].graphMax,
1528                    sequences[i].getAnnotation()[a].graph);
1529
1530            sequences[i].getAnnotation()[a] = newAnnot;
1531            newAnnot.sequenceMapping = sequences[i].getAnnotation()[a].
1532                sequenceMapping;
1533            newAnnot.sequenceRef = sequences[i];
1534            newAnnot.adjustForAlignment();
1535            alignment.addAnnotation(newAnnot);
1536            alignment.setAnnotationIndex(newAnnot, a);
1537          }
1538
1539          alignPanel.annotationPanel.adjustPanelHeight();
1540        }
1541      }
1542
1543      if(newAlignment)
1544      {
1545        AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH, DEFAULT_HEIGHT);
1546        String newtitle = new String("Copied sequences");
1547
1548        if(Desktop.jalviewClipboard!=null && Desktop.jalviewClipboard[2]!=null)
1549          {
1550            Vector hc = (Vector)Desktop.jalviewClipboard[2];
1551            for(int i=0; i<hc.size(); i++)
1552            {
1553              int [] region = (int[]) hc.elementAt(i);
1554              af.viewport.hideColumns(region[0], region[1]);
1555            }
1556          }
1557
1558
1559        //>>>This is a fix for the moment, until a better solution is found!!<<<
1560        af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().transferSettings(
1561            alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
1562
1563
1564        if (title.startsWith("Copied sequences"))
1565        {
1566          newtitle = title;
1567        }
1568        else
1569        {
1570          newtitle = newtitle.concat("- from " + title);
1571        }
1572
1573        Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
1574                                 DEFAULT_HEIGHT);
1575
1576      }
1577
1578
1579     }
1580     catch (Exception ex)
1581     {
1582       ex.printStackTrace();
1583         System.out.println("Exception whilst pasting: "+ex);
1584         // could be anything being pasted in here
1585     }
1586
1587
1588   }
1589
1590   /**
1591    * DOCUMENT ME!
1592    *
1593    * @param e DOCUMENT ME!
1594    */
1595   protected void cut_actionPerformed(ActionEvent e)
1596   {
1597     copy_actionPerformed(null);
1598     delete_actionPerformed(null);
1599   }
1600
1601   /**
1602    * DOCUMENT ME!
1603    *
1604    * @param e DOCUMENT ME!
1605    */
1606   protected void delete_actionPerformed(ActionEvent evt)
1607   {
1608
1609     SequenceGroup sg = viewport.getSelectionGroup();
1610     if (sg == null)
1611     {
1612       return;
1613     }
1614
1615     Vector seqs = new Vector();
1616     SequenceI seq;
1617     for (int i = 0; i < sg.getSize(); i++)
1618     {
1619       seq = sg.getSequenceAt(i);
1620       seqs.addElement(seq);
1621     }
1622
1623
1624    // If the cut affects all sequences, remove highlighted columns
1625    if (sg.getSize() == viewport.alignment.getHeight())
1626    {
1627      viewport.getColumnSelection().removeElements(sg.getStartRes(),
1628          sg.getEndRes() + 1);
1629    }
1630
1631
1632     SequenceI [] cut = new SequenceI[seqs.size()];
1633     for(int i=0; i<seqs.size(); i++)
1634     {
1635       cut[i] = (SequenceI)seqs.elementAt(i);
1636     }
1637
1638
1639     /*
1640     //ADD HISTORY ITEM
1641     */
1642     addHistoryItem(new EditCommand("Cut Sequences",
1643                                       EditCommand.CUT,
1644                                       cut,
1645                                       sg.getStartRes(),
1646                                       sg.getEndRes()-sg.getStartRes()+1,
1647                                       viewport.alignment));
1648
1649
1650     viewport.setSelectionGroup(null);
1651     viewport.alignment.deleteGroup(sg);
1652
1653     viewport.firePropertyChange("alignment", null,
1654                                   viewport.getAlignment().getSequences());
1655
1656     if (viewport.getAlignment().getHeight() < 1)
1657     {
1658       try
1659       {
1660         this.setClosed(true);
1661       }
1662       catch (Exception ex)
1663       {
1664       }
1665     }
1666   }
1667
1668   /**
1669    * DOCUMENT ME!
1670    *
1671    * @param e DOCUMENT ME!
1672    */
1673   protected void deleteGroups_actionPerformed(ActionEvent e)
1674   {
1675     viewport.alignment.deleteAllGroups();
1676     viewport.sequenceColours = null;
1677     viewport.setSelectionGroup(null);
1678     PaintRefresher.Refresh(this, viewport.getSequenceSetId());
1679     alignPanel.paintAlignment(true);
1680   }
1681
1682   /**
1683    * DOCUMENT ME!
1684    *
1685    * @param e DOCUMENT ME!
1686    */
1687   public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
1688   {
1689     SequenceGroup sg = new SequenceGroup();
1690
1691     for (int i = 0; i < viewport.getAlignment().getSequences().size();
1692          i++)
1693     {
1694       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);
1695     }
1696
1697     sg.setEndRes(viewport.alignment.getWidth() - 1);
1698     viewport.setSelectionGroup(sg);
1699     alignPanel.paintAlignment(true);
1700     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1701   }
1702
1703   /**
1704    * DOCUMENT ME!
1705    *
1706    * @param e DOCUMENT ME!
1707    */
1708   public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
1709   {
1710     if(viewport.cursorMode)
1711     {
1712       alignPanel.seqPanel.keyboardNo1 = null;
1713       alignPanel.seqPanel.keyboardNo2 = null;
1714     }
1715     viewport.setSelectionGroup(null);
1716     viewport.getColumnSelection().clear();
1717     viewport.setSelectionGroup(null);
1718     alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);
1719     alignPanel.idPanel.idCanvas.searchResults = null;
1720     alignPanel.paintAlignment(true);
1721     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1722   }
1723
1724   /**
1725    * DOCUMENT ME!
1726    *
1727    * @param e DOCUMENT ME!
1728    */
1729   public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
1730   {
1731     SequenceGroup sg = viewport.getSelectionGroup();
1732
1733     if (sg == null)
1734     {
1735       selectAllSequenceMenuItem_actionPerformed(null);
1736
1737       return;
1738     }
1739
1740     for (int i = 0; i < viewport.getAlignment().getSequences().size();
1741          i++)
1742     {
1743       sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
1744     }
1745
1746     alignPanel.paintAlignment(true);
1747
1748     PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
1749   }
1750
1751   public void invertColSel_actionPerformed(ActionEvent e)
1752   {
1753     viewport.invertColumnSelection();
1754     alignPanel.paintAlignment(true);
1755   }
1756
1757
1758   /**
1759    * DOCUMENT ME!
1760    *
1761    * @param e DOCUMENT ME!
1762    */
1763   public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
1764   {
1765     trimAlignment(true);
1766   }
1767
1768   /**
1769    * DOCUMENT ME!
1770    *
1771    * @param e DOCUMENT ME!
1772    */
1773   public void remove2RightMenuItem_actionPerformed(ActionEvent e)
1774   {
1775       trimAlignment(false);
1776   }
1777
1778   void trimAlignment(boolean trimLeft)
1779   {
1780     ColumnSelection colSel = viewport.getColumnSelection();
1781     int column;
1782
1783     if (colSel.size() > 0)
1784     {
1785       if(trimLeft)
1786       {
1787         column = colSel.getMin();
1788       }
1789       else
1790       {
1791         column = colSel.getMax();
1792       }
1793
1794       SequenceI [] seqs;
1795       if(viewport.getSelectionGroup()!=null)
1796       {
1797         seqs = viewport.getSelectionGroup().getSequencesAsArray(viewport.
1798             hiddenRepSequences);
1799       }
1800       else
1801       {
1802         seqs = viewport.alignment.getSequencesArray();
1803       }
1804
1805
1806       TrimRegionCommand trimRegion;
1807       if(trimLeft)
1808       {
1809         trimRegion = new TrimRegionCommand("Remove Left",
1810                                     TrimRegionCommand.TRIM_LEFT,
1811                                     seqs,
1812                                     column,
1813                                     viewport.alignment,
1814                                     viewport.colSel,
1815                                     viewport.selectionGroup);
1816         viewport.setStartRes(0);
1817       }
1818      else
1819      {
1820        trimRegion = new TrimRegionCommand("Remove Right",
1821                                    TrimRegionCommand.TRIM_RIGHT,
1822                                    seqs,
1823                                    column,
1824                                    viewport.alignment,
1825                                    viewport.colSel,
1826                                    viewport.selectionGroup);
1827      }
1828
1829      statusBar.setText("Removed "+trimRegion.getSize()+" columns.");
1830
1831
1832       addHistoryItem(trimRegion);
1833
1834       Vector groups = viewport.alignment.getGroups();
1835
1836       for (int i = 0; i < groups.size(); i++)
1837       {
1838         SequenceGroup sg = (SequenceGroup) groups.get(i);
1839
1840         if ( (trimLeft && !sg.adjustForRemoveLeft(column))
1841             || (!trimLeft && !sg.adjustForRemoveRight(column)))
1842         {
1843           viewport.alignment.deleteGroup(sg);
1844         }
1845       }
1846
1847       viewport.firePropertyChange("alignment", null,
1848                                   viewport.getAlignment().getSequences());
1849     }
1850   }
1851
1852   /**
1853    * DOCUMENT ME!
1854    *
1855    * @param e DOCUMENT ME!
1856    */
1857   public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
1858   {
1859     int start = 0, end = viewport.alignment.getWidth()-1;
1860
1861     SequenceI[] seqs;
1862     if (viewport.getSelectionGroup() != null)
1863     {
1864       seqs = viewport.getSelectionGroup().getSequencesAsArray(viewport.
1865           hiddenRepSequences);
1866       start = viewport.getSelectionGroup().getStartRes();
1867       end = viewport.getSelectionGroup().getEndRes();
1868     }
1869     else
1870     {
1871       seqs = viewport.alignment.getSequencesArray();
1872     }
1873
1874
1875     RemoveGapColCommand removeGapCols =
1876         new RemoveGapColCommand("Remove Gapped Columns",
1877                                 seqs,
1878                                 start, end,
1879                                 viewport.alignment);
1880
1881     addHistoryItem(removeGapCols);
1882
1883     statusBar.setText("Removed "+removeGapCols.getSize()+" empty columns.");
1884
1885     //This is to maintain viewport position on first residue
1886     //of first sequence
1887     SequenceI seq = viewport.alignment.getSequenceAt(0);
1888     int startRes = seq.findPosition(viewport.startRes);
1889    // ShiftList shifts;
1890    // viewport.getAlignment().removeGaps(shifts=new ShiftList());
1891    // edit.alColumnChanges=shifts.getInverse();
1892    // if (viewport.hasHiddenColumns)
1893    //   viewport.getColumnSelection().compensateForEdits(shifts);
1894    viewport.setStartRes(seq.findIndex(startRes)-1);
1895     viewport.firePropertyChange("alignment", null,
1896                                 viewport.getAlignment().getSequences());
1897
1898   }
1899
1900   /**
1901    * DOCUMENT ME!
1902    *
1903    * @param e DOCUMENT ME!
1904    */
1905   public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
1906   {
1907     int start = 0, end = viewport.alignment.getWidth()-1;
1908
1909     SequenceI[] seqs;
1910     if (viewport.getSelectionGroup() != null)
1911     {
1912       seqs = viewport.getSelectionGroup().getSequencesAsArray(viewport.
1913           hiddenRepSequences);
1914       start = viewport.getSelectionGroup().getStartRes();
1915       end = viewport.getSelectionGroup().getEndRes();
1916     }
1917     else
1918     {
1919       seqs = viewport.alignment.getSequencesArray();
1920     }
1921
1922     //This is to maintain viewport position on first residue
1923     //of first sequence
1924     SequenceI seq = viewport.alignment.getSequenceAt(0);
1925     int startRes = seq.findPosition(viewport.startRes);
1926
1927     addHistoryItem(new RemoveGapsCommand("Remove Gaps",
1928                                          seqs,
1929                                          start, end,
1930                                          viewport.alignment));
1931
1932     viewport.setStartRes(seq.findIndex(startRes)-1);
1933
1934     viewport.firePropertyChange("alignment", null,
1935                                 viewport.getAlignment().getSequences());
1936
1937   }
1938
1939   /**
1940    * DOCUMENT ME!
1941    *
1942    * @param e DOCUMENT ME!
1943    */
1944   public void padGapsMenuitem_actionPerformed(ActionEvent e)
1945   {
1946     viewport.padGaps = padGapsMenuitem.isSelected();
1947
1948     viewport.firePropertyChange("alignment",
1949                                 null,
1950                                 viewport.getAlignment().getSequences());
1951   }
1952
1953   /**
1954    * DOCUMENT ME!
1955    *
1956    * @param e DOCUMENT ME!
1957    */
1958   public void findMenuItem_actionPerformed(ActionEvent e)
1959   {
1960     new Finder();
1961   }
1962
1963   public void newView_actionPerformed(ActionEvent e)
1964   {
1965     AlignmentPanel newap =
1966         new Jalview2XML().copyAlignPanel(alignPanel, true);
1967
1968     newap.av.gatherViewsHere = false;
1969
1970     if (viewport.viewName == null)
1971     {
1972       viewport.viewName = "Original";
1973     }
1974
1975     newap.av.historyList = viewport.historyList;
1976     newap.av.redoList = viewport.redoList;
1977
1978     int index = Desktop.getViewCount(viewport.getSequenceSetId());
1979     String newViewName = "View " +index;
1980
1981     Vector comps = (Vector) PaintRefresher.components.get(viewport.
1982         getSequenceSetId());
1983     Vector existingNames = new Vector();
1984     for(int i=0; i<comps.size(); i++)
1985     {
1986       if(comps.elementAt(i) instanceof AlignmentPanel)
1987       {
1988         AlignmentPanel ap = (AlignmentPanel)comps.elementAt(i);
1989         if(!existingNames.contains(ap.av.viewName))
1990         {
1991           existingNames.addElement(ap.av.viewName);
1992       }
1993     }
1994     }
1995
1996     while(existingNames.contains(newViewName))
1997     {
1998       newViewName = "View "+ (++index);
1999     }
2000
2001     newap.av.viewName = newViewName;
2002
2003     addAlignmentPanel(newap, false);
2004
2005     if(alignPanels.size()==2)
2006     {
2007       viewport.gatherViewsHere = true;
2008     }
2009     tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
2010   }
2011
2012   public void expandViews_actionPerformed(ActionEvent e)
2013   {
2014         Desktop.instance.explodeViews(this);
2015   }
2016
2017   public void gatherViews_actionPerformed(ActionEvent e)
2018   {
2019     Desktop.instance.gatherViews(this);
2020   }
2021
2022
2023
2024   /**
2025    * DOCUMENT ME!
2026    *
2027    * @param e DOCUMENT ME!
2028    */
2029   public void font_actionPerformed(ActionEvent e)
2030   {
2031     new FontChooser(alignPanel);
2032   }
2033
2034
2035   /**
2036    * DOCUMENT ME!
2037    *
2038    * @param e DOCUMENT ME!
2039    */
2040   protected void seqLimit_actionPerformed(ActionEvent e)
2041   {
2042     viewport.setShowJVSuffix(seqLimits.isSelected());
2043
2044     alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel.calculateIdWidth());
2045     alignPanel.paintAlignment(true);
2046   }
2047
2048   public void idRightAlign_actionPerformed(ActionEvent e)
2049   {
2050     viewport.rightAlignIds = idRightAlign.isSelected();
2051     alignPanel.paintAlignment(true);
2052   }
2053
2054
2055
2056   /**
2057    * DOCUMENT ME!
2058    *
2059    * @param e DOCUMENT ME!
2060    */
2061   protected void colourTextMenuItem_actionPerformed(ActionEvent e)
2062   {
2063     viewport.setColourText(colourTextMenuItem.isSelected());
2064     alignPanel.paintAlignment(true);
2065   }
2066
2067   /**
2068    * DOCUMENT ME!
2069    *
2070    * @param e DOCUMENT ME!
2071    */
2072   public void wrapMenuItem_actionPerformed(ActionEvent e)
2073   {
2074     scaleAbove.setVisible(wrapMenuItem.isSelected());
2075     scaleLeft.setVisible(wrapMenuItem.isSelected());
2076     scaleRight.setVisible(wrapMenuItem.isSelected());
2077     viewport.setWrapAlignment(wrapMenuItem.isSelected());
2078     alignPanel.setWrapAlignment(wrapMenuItem.isSelected());
2079   }
2080
2081   public void showAllSeqs_actionPerformed(ActionEvent e)
2082   {
2083     viewport.showAllHiddenSeqs();
2084   }
2085
2086   public void showAllColumns_actionPerformed(ActionEvent e)
2087   {
2088     viewport.showAllHiddenColumns();
2089     repaint();
2090   }
2091
2092   public void hideSelSequences_actionPerformed(ActionEvent e)
2093   {
2094     viewport.hideAllSelectedSeqs();
2095     alignPanel.paintAlignment(true);
2096   }
2097
2098   public void hideSelColumns_actionPerformed(ActionEvent e)
2099   {
2100     viewport.hideSelectedColumns();
2101     alignPanel.paintAlignment(true);
2102   }
2103
2104   public void hiddenMarkers_actionPerformed(ActionEvent e)
2105   {
2106     viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
2107     repaint();
2108   }
2109
2110   /**
2111    * DOCUMENT ME!
2112    *
2113    * @param e DOCUMENT ME!
2114    */
2115   protected void scaleAbove_actionPerformed(ActionEvent e)
2116   {
2117     viewport.setScaleAboveWrapped(scaleAbove.isSelected());
2118     alignPanel.paintAlignment(true);
2119   }
2120
2121   /**
2122    * DOCUMENT ME!
2123    *
2124    * @param e DOCUMENT ME!
2125    */
2126   protected void scaleLeft_actionPerformed(ActionEvent e)
2127   {
2128     viewport.setScaleLeftWrapped(scaleLeft.isSelected());
2129     alignPanel.paintAlignment(true);
2130   }
2131
2132   /**
2133    * DOCUMENT ME!
2134    *
2135    * @param e DOCUMENT ME!
2136    */
2137   protected void scaleRight_actionPerformed(ActionEvent e)
2138   {
2139     viewport.setScaleRightWrapped(scaleRight.isSelected());
2140     alignPanel.paintAlignment(true);
2141   }
2142
2143   /**
2144    * DOCUMENT ME!
2145    *
2146    * @param e DOCUMENT ME!
2147    */
2148   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
2149   {
2150     viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
2151     alignPanel.paintAlignment(true);
2152   }
2153
2154   /**
2155    * DOCUMENT ME!
2156    *
2157    * @param e DOCUMENT ME!
2158    */
2159   public void viewTextMenuItem_actionPerformed(ActionEvent e)
2160   {
2161     viewport.setShowText(viewTextMenuItem.isSelected());
2162     alignPanel.paintAlignment(true);
2163   }
2164
2165   /**
2166    * DOCUMENT ME!
2167    *
2168    * @param e DOCUMENT ME!
2169    */
2170   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
2171   {
2172     viewport.setRenderGaps(renderGapsMenuItem.isSelected());
2173     alignPanel.paintAlignment(true);
2174   }
2175
2176
2177   public FeatureSettings featureSettings;
2178   public void featureSettings_actionPerformed(ActionEvent e)
2179   {
2180     if(featureSettings !=null )
2181     {
2182       featureSettings.close();
2183       featureSettings = null;
2184     }
2185     featureSettings = new FeatureSettings(this);
2186   }
2187
2188   /**
2189    * DOCUMENT ME!
2190    *
2191    * @param evt DOCUMENT ME!
2192    */
2193   public void showSeqFeatures_actionPerformed(ActionEvent evt)
2194   {
2195     viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
2196     alignPanel.paintAlignment(true);
2197     if (alignPanel.getOverviewPanel() != null)
2198     {
2199       alignPanel.getOverviewPanel().updateOverviewImage();
2200     }
2201   }
2202
2203   /**
2204    * DOCUMENT ME!
2205    *
2206    * @param e DOCUMENT ME!
2207    */
2208   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
2209   {
2210     viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());
2211     alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());
2212   }
2213
2214   /**
2215    * DOCUMENT ME!
2216    *
2217    * @param e DOCUMENT ME!
2218    */
2219   public void overviewMenuItem_actionPerformed(ActionEvent e)
2220   {
2221     if (alignPanel.overviewPanel != null)
2222     {
2223       return;
2224     }
2225
2226     JInternalFrame frame = new JInternalFrame();
2227     OverviewPanel overview = new OverviewPanel(alignPanel);
2228     frame.setContentPane(overview);
2229     Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),
2230                              frame.getWidth(), frame.getHeight());
2231     frame.pack();
2232     frame.setLayer(JLayeredPane.PALETTE_LAYER);
2233     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
2234     {
2235       public void internalFrameClosed(
2236           javax.swing.event.InternalFrameEvent evt)
2237       {
2238         alignPanel.setOverviewPanel(null);
2239       }
2240       ;
2241     });
2242
2243     alignPanel.setOverviewPanel(overview);
2244   }
2245
2246   public void textColour_actionPerformed(ActionEvent e)
2247   {
2248     new TextColourChooser().chooseColour(alignPanel, null);
2249   }
2250
2251   /**
2252    * DOCUMENT ME!
2253    *
2254    * @param e DOCUMENT ME!
2255    */
2256   protected void noColourmenuItem_actionPerformed(ActionEvent e)
2257   {
2258     changeColour(null);
2259   }
2260
2261   /**
2262    * DOCUMENT ME!
2263    *
2264    * @param e DOCUMENT ME!
2265    */
2266   public void clustalColour_actionPerformed(ActionEvent e)
2267   {
2268     changeColour(new ClustalxColourScheme(
2269         viewport.alignment.getSequences(), viewport.alignment.getWidth()));
2270   }
2271
2272   /**
2273    * DOCUMENT ME!
2274    *
2275    * @param e DOCUMENT ME!
2276    */
2277   public void zappoColour_actionPerformed(ActionEvent e)
2278   {
2279     changeColour(new ZappoColourScheme());
2280   }
2281
2282   /**
2283    * DOCUMENT ME!
2284    *
2285    * @param e DOCUMENT ME!
2286    */
2287   public void taylorColour_actionPerformed(ActionEvent e)
2288   {
2289     changeColour(new TaylorColourScheme());
2290   }
2291
2292   /**
2293    * DOCUMENT ME!
2294    *
2295    * @param e DOCUMENT ME!
2296    */
2297   public void hydrophobicityColour_actionPerformed(ActionEvent e)
2298   {
2299     changeColour(new HydrophobicColourScheme());
2300   }
2301
2302   /**
2303    * DOCUMENT ME!
2304    *
2305    * @param e DOCUMENT ME!
2306    */
2307   public void helixColour_actionPerformed(ActionEvent e)
2308   {
2309     changeColour(new HelixColourScheme());
2310   }
2311
2312   /**
2313    * DOCUMENT ME!
2314    *
2315    * @param e DOCUMENT ME!
2316    */
2317   public void strandColour_actionPerformed(ActionEvent e)
2318   {
2319     changeColour(new StrandColourScheme());
2320   }
2321
2322   /**
2323    * DOCUMENT ME!
2324    *
2325    * @param e DOCUMENT ME!
2326    */
2327   public void turnColour_actionPerformed(ActionEvent e)
2328   {
2329     changeColour(new TurnColourScheme());
2330   }
2331
2332   /**
2333    * DOCUMENT ME!
2334    *
2335    * @param e DOCUMENT ME!
2336    */
2337   public void buriedColour_actionPerformed(ActionEvent e)
2338   {
2339     changeColour(new BuriedColourScheme());
2340   }
2341
2342   /**
2343    * DOCUMENT ME!
2344    *
2345    * @param e DOCUMENT ME!
2346    */
2347   public void nucleotideColour_actionPerformed(ActionEvent e)
2348   {
2349     changeColour(new NucleotideColourScheme());
2350   }
2351
2352   public void annotationColour_actionPerformed(ActionEvent e)
2353   {
2354     new AnnotationColourChooser(viewport, alignPanel);
2355   }
2356
2357
2358   /**
2359    * DOCUMENT ME!
2360    *
2361    * @param e DOCUMENT ME!
2362    */
2363   protected void applyToAllGroups_actionPerformed(ActionEvent e)
2364   {
2365     viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
2366   }
2367
2368   /**
2369    * DOCUMENT ME!
2370    *
2371    * @param cs DOCUMENT ME!
2372    */
2373   public void changeColour(ColourSchemeI cs)
2374   {
2375     int threshold = 0;
2376
2377     if(cs!=null)
2378     {
2379       if (viewport.getAbovePIDThreshold())
2380       {
2381         threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,
2382                                                    "Background");
2383
2384         cs.setThreshold(threshold,
2385                         viewport.getIgnoreGapsConsensus());
2386
2387         viewport.setGlobalColourScheme(cs);
2388       }
2389       else
2390       {
2391         cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2392       }
2393
2394       if (viewport.getConservationSelected())
2395       {
2396
2397         Alignment al = (Alignment) viewport.alignment;
2398         Conservation c = new Conservation("All",
2399                                           ResidueProperties.propHash, 3,
2400                                           al.getSequences(), 0,
2401                                           al.getWidth() - 1);
2402
2403         c.calculate();
2404         c.verdict(false, viewport.ConsPercGaps);
2405
2406         cs.setConservation(c);
2407
2408         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,
2409             "Background"));
2410       }
2411       else
2412       {
2413         cs.setConservation(null);
2414       }
2415
2416       cs.setConsensus(viewport.hconsensus);
2417     }
2418
2419     viewport.setGlobalColourScheme(cs);
2420
2421     if (viewport.getColourAppliesToAllGroups())
2422     {
2423       Vector groups = viewport.alignment.getGroups();
2424
2425       for (int i = 0; i < groups.size(); i++)
2426       {
2427         SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
2428
2429         if (cs == null)
2430         {
2431           sg.cs = null;
2432           continue;
2433         }
2434
2435         if (cs instanceof ClustalxColourScheme)
2436         {
2437           sg.cs = new ClustalxColourScheme(
2438               sg.getSequences(viewport.hiddenRepSequences), sg.getWidth());
2439         }
2440         else if (cs instanceof UserColourScheme)
2441         {
2442           sg.cs = new UserColourScheme( ( (UserColourScheme) cs).getColours());
2443         }
2444         else
2445         {
2446           try
2447           {
2448             sg.cs = (ColourSchemeI) cs.getClass().newInstance();
2449           }
2450           catch (Exception ex)
2451           {
2452           }
2453         }
2454
2455         if (viewport.getAbovePIDThreshold()
2456             || cs instanceof PIDColourScheme
2457             || cs instanceof Blosum62ColourScheme)
2458         {
2459          sg.cs.setThreshold(threshold,
2460                 viewport.getIgnoreGapsConsensus());
2461
2462          sg.cs.setConsensus(AAFrequency.calculate(
2463              sg.getSequences(viewport.hiddenRepSequences), sg.getStartRes(),
2464              sg.getEndRes()+1));
2465        }
2466         else
2467         {
2468           sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
2469         }
2470
2471
2472         if (viewport.getConservationSelected())
2473         {
2474           Conservation c = new Conservation("Group",
2475                                             ResidueProperties.propHash, 3,
2476                                             sg.getSequences(viewport.
2477               hiddenRepSequences),
2478                                             sg.getStartRes(),
2479                                             sg.getEndRes()+1);
2480           c.calculate();
2481           c.verdict(false, viewport.ConsPercGaps);
2482           sg.cs.setConservation(c);
2483         }
2484         else
2485         {
2486           sg.cs.setConservation(null);
2487       }
2488     }
2489     }
2490
2491     if (alignPanel.getOverviewPanel() != null)
2492     {
2493       alignPanel.getOverviewPanel().updateOverviewImage();
2494     }
2495
2496
2497
2498
2499     alignPanel.paintAlignment(true);
2500   }
2501
2502   /**
2503    * DOCUMENT ME!
2504    *
2505    * @param e DOCUMENT ME!
2506    */
2507   protected void modifyPID_actionPerformed(ActionEvent e)
2508   {
2509     if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme!=null)
2510     {
2511       SliderPanel.setPIDSliderSource(alignPanel,
2512                                      viewport.getGlobalColourScheme(),
2513                                      "Background");
2514       SliderPanel.showPIDSlider();
2515     }
2516   }
2517
2518   /**
2519    * DOCUMENT ME!
2520    *
2521    * @param e DOCUMENT ME!
2522    */
2523   protected void modifyConservation_actionPerformed(ActionEvent e)
2524   {
2525     if (viewport.getConservationSelected() && viewport.globalColourScheme!=null)
2526     {
2527       SliderPanel.setConservationSlider(alignPanel,
2528                                         viewport.globalColourScheme,
2529                                         "Background");
2530       SliderPanel.showConservationSlider();
2531     }
2532   }
2533
2534   /**
2535    * DOCUMENT ME!
2536    *
2537    * @param e DOCUMENT ME!
2538    */
2539   protected void conservationMenuItem_actionPerformed(ActionEvent e)
2540   {
2541     viewport.setConservationSelected(conservationMenuItem.isSelected());
2542
2543     viewport.setAbovePIDThreshold(false);
2544     abovePIDThreshold.setSelected(false);
2545
2546     changeColour(viewport.getGlobalColourScheme());
2547
2548     modifyConservation_actionPerformed(null);
2549   }
2550
2551   /**
2552    * DOCUMENT ME!
2553    *
2554    * @param e DOCUMENT ME!
2555    */
2556   public void abovePIDThreshold_actionPerformed(ActionEvent e)
2557   {
2558     viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());
2559
2560     conservationMenuItem.setSelected(false);
2561     viewport.setConservationSelected(false);
2562
2563     changeColour(viewport.getGlobalColourScheme());
2564
2565     modifyPID_actionPerformed(null);
2566   }
2567
2568   /**
2569    * DOCUMENT ME!
2570    *
2571    * @param e DOCUMENT ME!
2572    */
2573   public void userDefinedColour_actionPerformed(ActionEvent e)
2574   {
2575     if (e.getActionCommand().equals("User Defined..."))
2576     {
2577       new UserDefinedColours(alignPanel, null);
2578     }
2579     else
2580     {
2581       UserColourScheme udc = (UserColourScheme) UserDefinedColours.
2582           getUserColourSchemes().get(e.getActionCommand());
2583
2584       changeColour(udc);
2585     }
2586   }
2587
2588   public void updateUserColourMenu()
2589   {
2590
2591     Component[] menuItems = colourMenu.getMenuComponents();
2592     int i, iSize = menuItems.length;
2593     for (i = 0; i < iSize; i++)
2594     {
2595       if (menuItems[i].getName() != null &&
2596           menuItems[i].getName().equals("USER_DEFINED"))
2597       {
2598         colourMenu.remove(menuItems[i]);
2599         iSize--;
2600       }
2601     }
2602     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
2603     {
2604       java.util.Enumeration userColours = jalview.gui.UserDefinedColours.
2605           getUserColourSchemes().keys();
2606
2607       while (userColours.hasMoreElements())
2608       {
2609         final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
2610             userColours.
2611             nextElement().toString());
2612         radioItem.setName("USER_DEFINED");
2613         radioItem.addMouseListener(new MouseAdapter()
2614             {
2615               public void mousePressed(MouseEvent evt)
2616               {
2617                 if(evt.isControlDown() || SwingUtilities.isRightMouseButton(evt))
2618                 {
2619                   radioItem.removeActionListener(radioItem.getActionListeners()[0]);
2620
2621               int option = JOptionPane.showInternalConfirmDialog(jalview.gui.
2622                   Desktop.desktop,
2623                       "Remove from default list?",
2624                       "Remove user defined colour",
2625                       JOptionPane.YES_NO_OPTION);
2626                   if(option == JOptionPane.YES_OPTION)
2627                   {
2628                 jalview.gui.UserDefinedColours.removeColourFromDefaults(
2629                     radioItem.getText());
2630                     colourMenu.remove(radioItem);
2631                   }
2632                   else
2633               {
2634                     radioItem.addActionListener(new ActionListener()
2635                     {
2636                       public void actionPerformed(ActionEvent evt)
2637                       {
2638                         userDefinedColour_actionPerformed(evt);
2639                       }
2640                     });
2641                 }
2642               }
2643           }
2644             });
2645         radioItem.addActionListener(new ActionListener()
2646         {
2647           public void actionPerformed(ActionEvent evt)
2648           {
2649             userDefinedColour_actionPerformed(evt);
2650           }
2651         });
2652
2653         colourMenu.insert(radioItem, 15);
2654         colours.add(radioItem);
2655       }
2656     }
2657   }
2658
2659   /**
2660    * DOCUMENT ME!
2661    *
2662    * @param e DOCUMENT ME!
2663    */
2664   public void PIDColour_actionPerformed(ActionEvent e)
2665   {
2666     changeColour(new PIDColourScheme());
2667   }
2668
2669   /**
2670    * DOCUMENT ME!
2671    *
2672    * @param e DOCUMENT ME!
2673    */
2674   public void BLOSUM62Colour_actionPerformed(ActionEvent e)
2675   {
2676     changeColour(new Blosum62ColourScheme());
2677   }
2678
2679   /**
2680    * DOCUMENT ME!
2681    *
2682    * @param e DOCUMENT ME!
2683    */
2684   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
2685   {
2686     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2687     AlignmentSorter.sortByPID(viewport.getAlignment(),
2688                               viewport.getAlignment().getSequenceAt(0));
2689     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
2690                                     viewport.alignment));
2691     alignPanel.paintAlignment(true);
2692   }
2693
2694   /**
2695    * DOCUMENT ME!
2696    *
2697    * @param e DOCUMENT ME!
2698    */
2699   public void sortIDMenuItem_actionPerformed(ActionEvent e)
2700   {
2701     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2702     AlignmentSorter.sortByID(viewport.getAlignment());
2703     addHistoryItem(new OrderCommand("ID Sort", oldOrder, viewport.alignment));
2704     alignPanel.paintAlignment(true);
2705   }
2706
2707   /**
2708    * DOCUMENT ME!
2709    *
2710    * @param e DOCUMENT ME!
2711    */
2712   public void sortGroupMenuItem_actionPerformed(ActionEvent e)
2713   {
2714     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2715     AlignmentSorter.sortByGroup(viewport.getAlignment());
2716     addHistoryItem(new OrderCommand("Group Sort", oldOrder, viewport.alignment));
2717
2718     alignPanel.paintAlignment(true);
2719   }
2720
2721   /**
2722    * DOCUMENT ME!
2723    *
2724    * @param e DOCUMENT ME!
2725    */
2726   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
2727   {
2728     new RedundancyPanel(alignPanel, this);
2729   }
2730
2731
2732   /**
2733    * DOCUMENT ME!
2734    *
2735    * @param e DOCUMENT ME!
2736    */
2737   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
2738   {
2739     if ( (viewport.getSelectionGroup() == null) ||
2740         (viewport.getSelectionGroup().getSize() < 2))
2741     {
2742       JOptionPane.showInternalMessageDialog(this,
2743                                             "You must select at least 2 sequences.",
2744                                             "Invalid Selection",
2745                                             JOptionPane.WARNING_MESSAGE);
2746     }
2747     else
2748     {
2749       JInternalFrame frame = new JInternalFrame();
2750       frame.setContentPane(new PairwiseAlignPanel(viewport));
2751       Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);
2752     }
2753   }
2754
2755   /**
2756    * DOCUMENT ME!
2757    *
2758    * @param e DOCUMENT ME!
2759    */
2760   public void PCAMenuItem_actionPerformed(ActionEvent e)
2761   {
2762     if ( ( (viewport.getSelectionGroup() != null) &&
2763           (viewport.getSelectionGroup().getSize() < 4) &&
2764           (viewport.getSelectionGroup().getSize() > 0)) ||
2765         (viewport.getAlignment().getHeight() < 4))
2766     {
2767       JOptionPane.showInternalMessageDialog(this,
2768                                             "Principal component analysis must take\n" +
2769                                             "at least 4 input sequences.",
2770                                             "Sequence selection insufficient",
2771                                             JOptionPane.WARNING_MESSAGE);
2772
2773       return;
2774     }
2775
2776      new PCAPanel(alignPanel);
2777   }
2778
2779
2780   public void autoCalculate_actionPerformed(ActionEvent e)
2781   {
2782     viewport.autoCalculateConsensus = autoCalculate.isSelected();
2783     if(viewport.autoCalculateConsensus)
2784     {
2785       viewport.firePropertyChange("alignment",
2786                                   null,
2787                                   viewport.getAlignment().getSequences());
2788     }
2789   }
2790
2791
2792   /**
2793    * DOCUMENT ME!
2794    *
2795    * @param e DOCUMENT ME!
2796    */
2797   public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
2798   {
2799     NewTreePanel("AV", "PID", "Average distance tree using PID");
2800   }
2801
2802   /**
2803    * DOCUMENT ME!
2804    *
2805    * @param e DOCUMENT ME!
2806    */
2807   public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
2808   {
2809     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
2810   }
2811
2812   /**
2813    * DOCUMENT ME!
2814    *
2815    * @param e DOCUMENT ME!
2816    */
2817   protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
2818   {
2819     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
2820   }
2821
2822   /**
2823    * DOCUMENT ME!
2824    *
2825    * @param e DOCUMENT ME!
2826    */
2827   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
2828   {
2829     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
2830   }
2831
2832   /**
2833    * DOCUMENT ME!
2834    *
2835    * @param type DOCUMENT ME!
2836    * @param pwType DOCUMENT ME!
2837    * @param title DOCUMENT ME!
2838    */
2839   void NewTreePanel(String type, String pwType, String title)
2840   {
2841     TreePanel tp;
2842
2843     if (viewport.getSelectionGroup() != null)
2844     {
2845       if (viewport.getSelectionGroup().getSize() < 3)
2846       {
2847         JOptionPane.showMessageDialog(Desktop.desktop,
2848                                       "You need to have more than two sequences selected to build a tree!",
2849                                       "Not enough sequences",
2850                                       JOptionPane.WARNING_MESSAGE);
2851         return;
2852       }
2853
2854       int s = 0;
2855       SequenceGroup sg = viewport.getSelectionGroup();
2856
2857       /* Decide if the selection is a column region */
2858       while (s < sg.getSize())
2859       {
2860         if ( ( (SequenceI) sg.getSequences(null).elementAt(s++)).getLength() <
2861             sg.getEndRes())
2862         {
2863           JOptionPane.showMessageDialog(Desktop.desktop,
2864                                         "The selected region to create a tree may\nonly contain residues or gaps.\n" +
2865                                         "Try using the Pad function in the edit menu,\n" +
2866                                         "or one of the multiple sequence alignment web services.",
2867                                         "Sequences in selection are not aligned",
2868                                         JOptionPane.WARNING_MESSAGE);
2869
2870           return;
2871         }
2872       }
2873
2874       title = title + " on region";
2875       tp = new TreePanel(alignPanel, type, pwType);
2876     }
2877     else
2878     {
2879       //are the sequences aligned?
2880       if (!viewport.alignment.isAligned())
2881       {
2882         JOptionPane.showMessageDialog(Desktop.desktop,
2883                                       "The sequences must be aligned before creating a tree.\n" +
2884                                       "Try using the Pad function in the edit menu,\n" +
2885                                       "or one of the multiple sequence alignment web services.",
2886                                       "Sequences not aligned",
2887                                       JOptionPane.WARNING_MESSAGE);
2888
2889         return;
2890       }
2891
2892       if(viewport.alignment.getHeight()<2)
2893       {
2894         return;
2895       }
2896
2897       tp = new TreePanel(alignPanel, type, pwType);
2898     }
2899
2900     title += " from ";
2901
2902     if(viewport.viewName!=null)
2903     {
2904       title+= viewport.viewName+" of ";
2905     }
2906
2907     title += this.title;
2908
2909     Desktop.addInternalFrame(tp, title, 600, 500);
2910   }
2911
2912   /**
2913    * DOCUMENT ME!
2914    *
2915    * @param title DOCUMENT ME!
2916    * @param order DOCUMENT ME!
2917    */
2918   public void addSortByOrderMenuItem(String title, final AlignmentOrder order)
2919   {
2920     final JMenuItem item = new JMenuItem("by " + title);
2921     sort.add(item);
2922     item.addActionListener(new java.awt.event.ActionListener()
2923     {
2924       public void actionPerformed(ActionEvent e)
2925       {
2926         SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2927
2928         // TODO: JBPNote - have to map order entries to curent SequenceI pointers
2929         AlignmentSorter.sortBy(viewport.getAlignment(), order);
2930
2931         addHistoryItem(new OrderCommand(order.getName(), oldOrder,
2932                                         viewport.alignment));
2933
2934         alignPanel.paintAlignment(true);
2935       }
2936     });
2937   }
2938
2939   /**
2940    * Maintain the Order by->Displayed Tree menu.
2941    * Creates a new menu item for a TreePanel with an appropriate
2942    * <code>jalview.analysis.AlignmentSorter</code> call. Listeners are added
2943    * to remove the menu item when the treePanel is closed, and adjust
2944    * the tree leaf to sequence mapping when the alignment is modified.
2945    * @param treePanel Displayed tree window.
2946    * @param title SortBy menu item title.
2947    */
2948   public void buildTreeMenu()
2949   {
2950     sortByTreeMenu.removeAll();
2951
2952     Vector comps = (Vector) PaintRefresher.components.get(viewport.
2953         getSequenceSetId());
2954     Vector treePanels = new Vector();
2955     int i, iSize = comps.size();
2956     for(i=0; i<iSize; i++)
2957     {
2958       if(comps.elementAt(i) instanceof TreePanel)
2959       {
2960         treePanels.add(comps.elementAt(i));
2961       }
2962     }
2963
2964     iSize = treePanels.size();
2965
2966     if(iSize<1)
2967     {
2968       sortByTreeMenu.setVisible(false);
2969       return;
2970     }
2971
2972     sortByTreeMenu.setVisible(true);
2973
2974     for(i=0; i<treePanels.size(); i++)
2975     {
2976       TreePanel tp = (TreePanel)treePanels.elementAt(i);
2977       final JMenuItem item = new JMenuItem(tp.getTitle());
2978       final NJTree tree = ((TreePanel)treePanels.elementAt(i)).getTree();
2979       item.addActionListener(new java.awt.event.ActionListener()
2980       {
2981         public void actionPerformed(ActionEvent e)
2982         {
2983           SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2984           AlignmentSorter.sortByTree(viewport.getAlignment(), tree);
2985
2986           addHistoryItem(new OrderCommand("Tree Sort",
2987                                           oldOrder,
2988                                           viewport.alignment));
2989
2990           alignPanel.paintAlignment(true);
2991         }
2992       });
2993
2994       sortByTreeMenu.add(item);
2995     }
2996   }
2997
2998   /**
2999    * Work out whether the whole set of sequences
3000    * or just the selected set will be submitted for multiple alignment.
3001    *
3002    */
3003   private jalview.datamodel.AlignmentView gatherSequencesForAlignment()
3004   {
3005     // Now, check we have enough sequences
3006     AlignmentView msa = null;
3007
3008     if ( (viewport.getSelectionGroup() != null) &&
3009         (viewport.getSelectionGroup().getSize() > 1))
3010     {
3011       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
3012       /*SequenceGroup seqs = viewport.getSelectionGroup();
3013       int sz;
3014       msa = new SequenceI[sz = seqs.getSize(false)];
3015
3016       for (int i = 0; i < sz; i++)
3017       {
3018         msa[i] = (SequenceI) seqs.getSequenceAt(i);
3019       } */
3020       msa = viewport.getAlignmentView(true);
3021     }
3022     else
3023     {
3024       /*Vector seqs = viewport.getAlignment().getSequences();
3025
3026       if (seqs.size() > 1)
3027       {
3028         msa = new SequenceI[seqs.size()];
3029
3030         for (int i = 0; i < seqs.size(); i++)
3031         {
3032           msa[i] = (SequenceI) seqs.elementAt(i);
3033         }
3034       }*/
3035       msa = viewport.getAlignmentView(false);
3036     }
3037     return msa;
3038   }
3039
3040   /**
3041    * Decides what is submitted to a secondary structure prediction service,
3042    * the currently selected sequence, or the currently selected alignment
3043    * (where the first sequence in the set is the one that the prediction
3044    * will be for).
3045    */
3046   AlignmentView gatherSeqOrMsaForSecStrPrediction()
3047   {
3048    AlignmentView seqs = null;
3049
3050     if ( (viewport.getSelectionGroup() != null) &&
3051         (viewport.getSelectionGroup().getSize() > 0))
3052     {
3053       seqs = viewport.getAlignmentView(true);
3054     }
3055     else
3056     {
3057       seqs = viewport.getAlignmentView(false);
3058     }
3059     // limit sequences - JBPNote in future - could spawn multiple prediction jobs
3060     // TODO: viewport.alignment.isAligned is a global state - the local selection may well be aligned - we preserve 2.0.8 behaviour for moment.
3061     if (!viewport.alignment.isAligned())
3062     {
3063       seqs.setSequences(new SeqCigar[]
3064                         {seqs.getSequences()[0]});
3065     }
3066     return seqs;
3067   }
3068   /**
3069    * DOCUMENT ME!
3070    *
3071    * @param e DOCUMENT ME!
3072    */
3073   protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)
3074   {
3075     // Pick the tree file
3076     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
3077         getProperty(
3078             "LAST_DIRECTORY"));
3079     chooser.setFileView(new JalviewFileView());
3080     chooser.setDialogTitle("Select a newick-like tree file");
3081     chooser.setToolTipText("Load a tree file");
3082
3083     int value = chooser.showOpenDialog(null);
3084
3085     if (value == JalviewFileChooser.APPROVE_OPTION)
3086     {
3087       String choice = chooser.getSelectedFile().getPath();
3088       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
3089
3090       try
3091       {
3092         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,
3093             "File");
3094         viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
3095       }
3096       catch (Exception ex)
3097       {
3098         JOptionPane.showMessageDialog(Desktop.desktop,
3099                                       "Problem reading tree file",
3100                                       ex.getMessage(),
3101                                       JOptionPane.WARNING_MESSAGE);
3102         ex.printStackTrace();
3103       }
3104     }
3105   }
3106
3107
3108   public TreePanel ShowNewickTree(NewickFile nf, String title)
3109   {
3110     return ShowNewickTree(nf,title,600,500,4,5);
3111   }
3112
3113   public TreePanel ShowNewickTree(NewickFile nf, String title,
3114                                   AlignmentView input)
3115   {
3116     return ShowNewickTree(nf,title, input, 600,500,4,5);
3117   }
3118
3119   public TreePanel ShowNewickTree(NewickFile nf, String title, int w, int h,
3120                                   int x, int y)
3121   {
3122     return ShowNewickTree(nf, title, null, w, h, x, y);
3123   }
3124   /**
3125    * Add a treeviewer for the tree extracted from a newick file object to the current alignment view
3126    *
3127    * @param nf the tree
3128    * @param title tree viewer title
3129    * @param input Associated alignment input data (or null)
3130    * @param w width
3131    * @param h height
3132    * @param x position
3133    * @param y position
3134    * @return TreePanel handle
3135    */
3136   public TreePanel ShowNewickTree(NewickFile nf, String title,
3137                                   AlignmentView input, int w, int h, int x,
3138                                   int y)
3139   {
3140     TreePanel tp = null;
3141
3142     try
3143     {
3144       nf.parse();
3145
3146       if (nf.getTree() != null)
3147       {
3148         tp = new TreePanel(alignPanel,
3149                            "FromFile",
3150                            title,
3151                            nf, input);
3152
3153         tp.setSize(w,h);
3154
3155         if(x>0 && y>0)
3156         {
3157           tp.setLocation(x,y);
3158         }
3159
3160
3161         Desktop.addInternalFrame(tp, title, w, h);
3162       }
3163     }
3164     catch (Exception ex)
3165     {
3166       ex.printStackTrace();
3167     }
3168
3169     return tp;
3170   }
3171
3172
3173   /**
3174    * Generates menu items and listener event actions for web service clients
3175    *
3176    */
3177   public void BuildWebServiceMenu()
3178   {
3179     if ( (Discoverer.services != null)
3180         && (Discoverer.services.size() > 0))
3181     {
3182       Vector msaws = (Vector) Discoverer.services.get("MsaWS");
3183       Vector secstrpr = (Vector) Discoverer.services.get("SecStrPred");
3184       Vector wsmenu = new Vector();
3185       final AlignFrame af = this;
3186       if (msaws != null)
3187       {
3188         // Add any Multiple Sequence Alignment Services
3189         final JMenu msawsmenu = new JMenu("Alignment");
3190         for (int i = 0, j = msaws.size(); i < j; i++)
3191         {
3192           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.
3193               get(i);
3194           final JMenuItem method = new JMenuItem(sh.getName());
3195           method.addActionListener(new ActionListener()
3196           {
3197             public void actionPerformed(ActionEvent e)
3198             {
3199               AlignmentView msa = gatherSequencesForAlignment();
3200               new jalview.ws.MsaWSClient(sh, title, msa,
3201                                          false, true,
3202                                          viewport.getAlignment().getDataset(),
3203                                          af);
3204
3205             }
3206
3207           });
3208           msawsmenu.add(method);
3209           // Deal with services that we know accept partial alignments.
3210           if (sh.getName().indexOf("lustal") > -1)
3211           {
3212             // We know that ClustalWS can accept partial alignments for refinement.
3213             final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");
3214             methodR.addActionListener(new ActionListener()
3215             {
3216               public void actionPerformed(ActionEvent e)
3217               {
3218                 AlignmentView msa = gatherSequencesForAlignment();
3219                 new jalview.ws.MsaWSClient(sh, title, msa,
3220                                            true, true,
3221                                            viewport.getAlignment().getDataset(),
3222                                            af);
3223
3224               }
3225
3226             });
3227             msawsmenu.add(methodR);
3228
3229           }
3230         }
3231         wsmenu.add(msawsmenu);
3232       }
3233       if (secstrpr != null)
3234       {
3235         // Add any secondary structure prediction services
3236         final JMenu secstrmenu = new JMenu("Secondary Structure Prediction");
3237         for (int i = 0, j = secstrpr.size(); i < j; i++)
3238         {
3239           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)
3240               secstrpr.get(i);
3241           final JMenuItem method = new JMenuItem(sh.getName());
3242           method.addActionListener(new ActionListener()
3243           {
3244             public void actionPerformed(ActionEvent e)
3245             {
3246               AlignmentView msa = gatherSeqOrMsaForSecStrPrediction();
3247               if (msa.getSequences().length == 1)
3248               {
3249                 // Single Sequence prediction
3250                 new jalview.ws.JPredClient(sh, title, false, msa, af, true);
3251               }
3252               else
3253               {
3254                 if (msa.getSequences().length > 1)
3255                 {
3256                   // Sequence profile based prediction
3257                   new jalview.ws.JPredClient(sh,
3258                       title, true, msa, af, true);
3259                 }
3260               }
3261             }
3262           });
3263           secstrmenu.add(method);
3264         }
3265         wsmenu.add(secstrmenu);
3266       }
3267       this.webService.removeAll();
3268       for (int i = 0, j = wsmenu.size(); i < j; i++)
3269       {
3270         webService.add( (JMenu) wsmenu.get(i));
3271       }
3272     }
3273     else
3274     {
3275       this.webService.removeAll();
3276       this.webService.add(this.webServiceNoServices);
3277     }
3278     // TODO: add in rediscovery function
3279     // TODO: reduce code redundancy.
3280     // TODO: group services by location as well as function.
3281   }
3282
3283  /* public void vamsasStore_actionPerformed(ActionEvent e)
3284   {
3285     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
3286         getProperty("LAST_DIRECTORY"));
3287
3288     chooser.setFileView(new JalviewFileView());
3289     chooser.setDialogTitle("Export to Vamsas file");
3290     chooser.setToolTipText("Export");
3291
3292     int value = chooser.showSaveDialog(this);
3293
3294     if (value == JalviewFileChooser.APPROVE_OPTION)
3295     {
3296       jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);
3297       //vs.store(chooser.getSelectedFile().getAbsolutePath()   );
3298       vs.storeJalview( chooser.getSelectedFile().getAbsolutePath(), this);
3299     }
3300   }*/
3301
3302
3303
3304
3305 public void showTranslation_actionPerformed(ActionEvent e)
3306 {
3307   ///////////////////////////////
3308   // Collect Data to be translated/transferred
3309
3310   SequenceI [] selection = viewport.getSelectionAsNewSequence();
3311   String [] seqstring = viewport.getViewAsString(true);
3312   AlignmentI al  = null;
3313   try {
3314     al = jalview.analysis.Dna.CdnaTranslate(selection, seqstring, viewport.getViewAsVisibleContigs(true),
3315         viewport.getGapCharacter(), viewport.alignment.getAlignmentAnnotation(),
3316         viewport.alignment.getWidth());
3317   } catch (Exception ex) {
3318     al = null;
3319     jalview.bin.Cache.log.debug("Exception during translation.",ex);
3320   }
3321   if (al==null)
3322   {
3323     JOptionPane.showMessageDialog(Desktop.desktop,
3324         "Please select at least three bases in at least one sequence in order to perform a cDNA translation.",
3325         "Translation Failed",
3326         JOptionPane.WARNING_MESSAGE);
3327   } else {
3328     AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
3329     Desktop.addInternalFrame(af, "Translation of "+this.getTitle(),
3330                              DEFAULT_WIDTH,
3331                              DEFAULT_HEIGHT);
3332   }
3333 }
3334
3335 /**
3336  * DOCUMENT ME!
3337  *
3338  * @param String DOCUMENT ME!
3339  */
3340 public boolean parseFeaturesFile(String file, String type)
3341 {
3342     boolean featuresFile = false;
3343     try
3344     {
3345       featuresFile = new FeaturesFile(file,
3346           type).parse(viewport.alignment.getDataset(),
3347                                          alignPanel.seqPanel.seqCanvas.
3348                                          getFeatureRenderer().featureColours,
3349                                          false);
3350     }
3351     catch(Exception ex)
3352     {
3353       ex.printStackTrace();
3354     }
3355
3356     if(featuresFile)
3357     {
3358       viewport.showSequenceFeatures = true;
3359       showSeqFeatures.setSelected(true);
3360       alignPanel.paintAlignment(true);
3361     }
3362
3363     return featuresFile;
3364 }
3365
3366 public void dragEnter(DropTargetDragEvent evt)
3367 {}
3368
3369 public void dragExit(DropTargetEvent evt)
3370 {}
3371
3372 public void dragOver(DropTargetDragEvent evt)
3373 {}
3374
3375 public void dropActionChanged(DropTargetDragEvent evt)
3376 {}
3377
3378 public void drop(DropTargetDropEvent evt)
3379 {
3380     Transferable t = evt.getTransferable();
3381     java.util.List files = null;
3382
3383     try
3384     {
3385       DataFlavor uriListFlavor = new DataFlavor(
3386           "text/uri-list;class=java.lang.String");
3387       if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3388       {
3389         //Works on Windows and MacOSX
3390         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3391         files = (java.util.List) t.getTransferData(DataFlavor.
3392             javaFileListFlavor);
3393       }
3394       else if (t.isDataFlavorSupported(uriListFlavor))
3395       {
3396         // This is used by Unix drag system
3397         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3398         String data = (String) t.getTransferData(uriListFlavor);
3399         files = new java.util.ArrayList(1);
3400         for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3401             data,
3402             "\r\n");
3403              st.hasMoreTokens(); )
3404         {
3405           String s = st.nextToken();
3406           if (s.startsWith("#"))
3407           {
3408             // the line is a comment (as per the RFC 2483)
3409             continue;
3410           }
3411
3412           java.net.URI uri = new java.net.URI(s);
3413           java.io.File file = new java.io.File(uri);
3414           files.add(file);
3415         }
3416       }
3417     }
3418     catch (Exception e)
3419     {
3420       e.printStackTrace();
3421     }
3422     if (files != null)
3423     {
3424       try
3425       {
3426
3427         for (int i = 0; i < files.size(); i++)
3428         {
3429           loadJalviewDataFile(files.get(i).toString());
3430         }
3431       }
3432       catch (Exception ex)
3433       {
3434         ex.printStackTrace();
3435       }
3436     }
3437 }
3438
3439   // This method will attempt to load a "dropped" file first by testing
3440   // whether its and Annotation file, then features file. If both are
3441   // false then the user may have dropped an alignment file onto this
3442   // AlignFrame
3443    public void loadJalviewDataFile(String file)
3444   {
3445     try
3446     {
3447       String protocol = "File";
3448
3449       if (file.indexOf("http:") > -1 || file.indexOf("file:") > -1)
3450       {
3451         protocol = "URL";
3452       }
3453
3454       boolean isAnnotation = new AnnotationFile().readAnnotationFile(viewport.
3455           alignment, file, protocol);
3456
3457       if (!isAnnotation)
3458       {
3459         boolean isGroupsFile = parseFeaturesFile(file,protocol);
3460         if (!isGroupsFile)
3461         {
3462           String format = new IdentifyFile().Identify(file, protocol);
3463
3464           if(format.equalsIgnoreCase("JnetFile"))
3465           {
3466             jalview.io.JPredFile predictions = new jalview.io.JPredFile(
3467                 file, protocol);
3468             new JnetAnnotationMaker().add_annotation(predictions,
3469                 viewport.getAlignment(),
3470                 0, false);
3471             alignPanel.adjustAnnotationHeight();
3472             alignPanel.paintAlignment(true);
3473           }
3474           else
3475           {
3476             new FileLoader().LoadFile(viewport, file, protocol, format);
3477         }
3478       }
3479       }
3480       else
3481       {
3482         // (isAnnotation)
3483         alignPanel.adjustAnnotationHeight();
3484       }
3485
3486     }
3487     catch (Exception ex)
3488     {
3489       ex.printStackTrace();
3490     }
3491   }
3492
3493   public void tabSelectionChanged(int index)
3494   {
3495     if (index > -1)
3496     {
3497       alignPanel = (AlignmentPanel) alignPanels.elementAt(index);
3498       viewport = alignPanel.av;
3499       setMenusFromViewport(viewport);
3500     }
3501   }
3502
3503   public void tabbedPane_mousePressed(MouseEvent e)
3504   {
3505     if(SwingUtilities.isRightMouseButton(e))
3506     {
3507       String reply = JOptionPane.showInternalInputDialog(this,
3508           "Enter View Name",
3509           "Edit View Name",
3510           JOptionPane.QUESTION_MESSAGE);
3511
3512       if (reply != null)
3513       {
3514         viewport.viewName = reply;
3515         tabbedPane.setTitleAt( tabbedPane.getSelectedIndex() ,reply);
3516       }
3517     }
3518   }
3519
3520
3521   public AlignViewport getCurrentView()
3522   {
3523     return viewport;
3524   }
3525 }
3526
3527 class PrintThread
3528     extends Thread
3529 {
3530   AlignmentPanel ap;
3531   public PrintThread(AlignmentPanel ap)
3532   {
3533    this.ap = ap;
3534   }
3535   static PageFormat pf;
3536   public void run()
3537   {
3538     PrinterJob printJob = PrinterJob.getPrinterJob();
3539
3540     if (pf != null)
3541     {
3542       printJob.setPrintable(ap, pf);
3543     }
3544     else
3545     {
3546       printJob.setPrintable(ap);
3547     }
3548
3549     if (printJob.printDialog())
3550     {
3551       try
3552       {
3553         printJob.print();
3554       }
3555       catch (Exception PrintException)
3556       {
3557         PrintException.printStackTrace();
3558       }
3559     }
3560   }
3561 }