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