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