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