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