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