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