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