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