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