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