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