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