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