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