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