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