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