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