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