Format changes
[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 += " from ";
2664
2665     if(viewport.viewName!=null)
2666       title+= viewport.viewName+" of ";
2667
2668     title += this.title;
2669
2670     Desktop.addInternalFrame(tp, title, 600, 500);
2671   }
2672
2673   /**
2674    * DOCUMENT ME!
2675    *
2676    * @param title DOCUMENT ME!
2677    * @param order DOCUMENT ME!
2678    */
2679   public void addSortByOrderMenuItem(String title, final AlignmentOrder order)
2680   {
2681     final JMenuItem item = new JMenuItem("by " + title);
2682     sort.add(item);
2683     item.addActionListener(new java.awt.event.ActionListener()
2684     {
2685       public void actionPerformed(ActionEvent e)
2686       {
2687         SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
2688
2689         // TODO: JBPNote - have to map order entries to curent SequenceI pointers
2690         AlignmentSorter.sortBy(viewport.getAlignment(), order);
2691
2692         addHistoryItem(new OrderCommand(order.getName(), oldOrder, viewport.alignment));
2693
2694         alignPanel.repaint();
2695       }
2696     });
2697   }
2698
2699   /**
2700    * Maintain the Order by->Displayed Tree menu.
2701    * Creates a new menu item for a TreePanel with an appropriate
2702    * <code>jalview.analysis.AlignmentSorter</code> call. Listeners are added
2703    * to remove the menu item when the treePanel is closed, and adjust
2704    * the tree leaf to sequence mapping when the alignment is modified.
2705    * @param treePanel Displayed tree window.
2706    * @param title SortBy menu item title.
2707    */
2708   public void buildTreeMenu()
2709   {
2710     sortByTreeMenu.removeAll();
2711
2712     Vector comps = (Vector)PaintRefresher.components.get(viewport.getSequenceSetId());
2713     Vector treePanels = new Vector();
2714     int i, iSize = comps.size();
2715     for(i=0; i<iSize; i++)
2716     {
2717       if(comps.elementAt(i) instanceof TreePanel)
2718       {
2719         treePanels.add(comps.elementAt(i));
2720       }
2721     }
2722
2723     iSize = treePanels.size();
2724
2725     if(iSize<1)
2726     {
2727       sortByTreeMenu.setVisible(false);
2728       return;
2729     }
2730
2731     sortByTreeMenu.setVisible(true);
2732
2733     for(i=0; i<treePanels.size(); i++)
2734     {
2735       TreePanel tp = (TreePanel)treePanels.elementAt(i);
2736       final JMenuItem item = new JMenuItem(tp.getTitle());
2737       final NJTree tree = ((TreePanel)treePanels.elementAt(i)).getTree();
2738       item.addActionListener(new java.awt.event.ActionListener()
2739       {
2740         public void actionPerformed(ActionEvent e)
2741         {
2742           SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
2743           AlignmentSorter.sortByTree(viewport.getAlignment(), tree);
2744
2745           addHistoryItem(new OrderCommand("Tree Sort",
2746                                           oldOrder,
2747                                           viewport.alignment));
2748
2749           alignPanel.repaint();
2750         }
2751       });
2752
2753       sortByTreeMenu.add(item);
2754     }
2755   }
2756
2757   /**
2758    * Work out whether the whole set of sequences
2759    * or just the selected set will be submitted for multiple alignment.
2760    *
2761    */
2762   private jalview.datamodel.AlignmentView gatherSequencesForAlignment()
2763   {
2764     // Now, check we have enough sequences
2765     AlignmentView msa = null;
2766
2767     if ( (viewport.getSelectionGroup() != null) &&
2768         (viewport.getSelectionGroup().getSize(false) > 1))
2769     {
2770       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
2771       /*SequenceGroup seqs = viewport.getSelectionGroup();
2772       int sz;
2773       msa = new SequenceI[sz = seqs.getSize(false)];
2774
2775       for (int i = 0; i < sz; i++)
2776       {
2777         msa[i] = (SequenceI) seqs.getSequenceAt(i);
2778       } */
2779       msa = viewport.getAlignmentView(true);
2780     }
2781     else
2782     {
2783       /*Vector seqs = viewport.getAlignment().getSequences();
2784
2785       if (seqs.size() > 1)
2786       {
2787         msa = new SequenceI[seqs.size()];
2788
2789         for (int i = 0; i < seqs.size(); i++)
2790         {
2791           msa[i] = (SequenceI) seqs.elementAt(i);
2792         }
2793       }*/
2794       msa = viewport.getAlignmentView(false);
2795     }
2796     return msa;
2797   }
2798
2799   /**
2800    * Decides what is submitted to a secondary structure prediction service,
2801    * the currently selected sequence, or the currently selected alignment
2802    * (where the first sequence in the set is the one that the prediction
2803    * will be for).
2804    */
2805   AlignmentView gatherSeqOrMsaForSecStrPrediction()
2806   {
2807    AlignmentView seqs = null;
2808
2809     if ( (viewport.getSelectionGroup() != null) &&
2810         (viewport.getSelectionGroup().getSize(false) > 0))
2811     {
2812       seqs = viewport.getAlignmentView(true);
2813     }
2814     else
2815     {
2816       seqs = viewport.getAlignmentView(false);
2817     }
2818     // limit sequences - JBPNote in future - could spawn multiple prediction jobs
2819     // TODO: viewport.alignment.isAligned is a global state - the local selection may well be aligned - we preserve 2.0.8 behaviour for moment.
2820     if (!viewport.alignment.isAligned())
2821     {
2822       seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] } );
2823     }
2824     return seqs;
2825   }
2826   /**
2827    * DOCUMENT ME!
2828    *
2829    * @param e DOCUMENT ME!
2830    */
2831   protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)
2832   {
2833     // Pick the tree file
2834     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
2835         getProperty(
2836             "LAST_DIRECTORY"));
2837     chooser.setFileView(new JalviewFileView());
2838     chooser.setDialogTitle("Select a newick-like tree file");
2839     chooser.setToolTipText("Load a tree file");
2840
2841     int value = chooser.showOpenDialog(null);
2842
2843     if (value == JalviewFileChooser.APPROVE_OPTION)
2844     {
2845       String choice = chooser.getSelectedFile().getPath();
2846       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
2847
2848       try
2849       {
2850         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,
2851             "File");
2852         viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
2853       }
2854       catch (Exception ex)
2855       {
2856         JOptionPane.showMessageDialog(Desktop.desktop,
2857                                       "Problem reading tree file",
2858                                       ex.getMessage(),
2859                                       JOptionPane.WARNING_MESSAGE);
2860         ex.printStackTrace();
2861       }
2862     }
2863   }
2864
2865
2866   public TreePanel ShowNewickTree(NewickFile nf, String title)
2867   {
2868     return ShowNewickTree(nf,title,600,500,4,5);
2869   }
2870   public TreePanel ShowNewickTree(NewickFile nf, String title, AlignmentView input)
2871   {
2872     return ShowNewickTree(nf,title, input, 600,500,4,5);
2873   }
2874   public TreePanel ShowNewickTree(NewickFile nf, String title, int w,int h,int x, int y) {
2875     return ShowNewickTree(nf, title, null, w, h, x, y);
2876   }
2877   /**
2878    * Add a treeviewer for the tree extracted from a newick file object to the current alignment view
2879    *
2880    * @param nf the tree
2881    * @param title tree viewer title
2882    * @param input Associated alignment input data (or null)
2883    * @param w width
2884    * @param h height
2885    * @param x position
2886    * @param y position
2887    * @return TreePanel handle
2888    */
2889   public TreePanel ShowNewickTree(NewickFile nf, String title, AlignmentView input, int w,int h,int x, int y) {
2890     TreePanel tp = null;
2891
2892     try
2893     {
2894       nf.parse();
2895
2896       if (nf.getTree() != null)
2897       {
2898         tp = new TreePanel(alignPanel,
2899                            "FromFile",
2900                            title,
2901                            nf, input);
2902
2903         tp.setSize(w,h);
2904
2905         if(x>0 && y>0)
2906           tp.setLocation(x,y);
2907
2908
2909         Desktop.addInternalFrame(tp, title, w, h);
2910       }
2911     }
2912     catch (Exception ex)
2913     {
2914       ex.printStackTrace();
2915     }
2916
2917     return tp;
2918   }
2919
2920   class PrintThread
2921       extends Thread
2922   {
2923     public void run()
2924     {
2925       PrinterJob printJob = PrinterJob.getPrinterJob();
2926       PageFormat pf = printJob.pageDialog(printJob.defaultPage());
2927       printJob.setPrintable(alignPanel, pf);
2928
2929       if (printJob.printDialog())
2930       {
2931         try
2932         {
2933           printJob.print();
2934         }
2935         catch (Exception PrintException)
2936         {
2937           PrintException.printStackTrace();
2938         }
2939       }
2940     }
2941   }
2942
2943   /**
2944    * Generates menu items and listener event actions for web service clients
2945    *
2946    */
2947   public void BuildWebServiceMenu()
2948   {
2949     if ( (Discoverer.services != null)
2950         && (Discoverer.services.size() > 0))
2951     {
2952       Vector msaws = (Vector) Discoverer.services.get("MsaWS");
2953       Vector secstrpr = (Vector) Discoverer.services.get("SecStrPred");
2954       Vector wsmenu = new Vector();
2955       final AlignFrame af = this;
2956       if (msaws != null)
2957       {
2958         // Add any Multiple Sequence Alignment Services
2959         final JMenu msawsmenu = new JMenu("Alignment");
2960         for (int i = 0, j = msaws.size(); i < j; i++)
2961         {
2962           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.
2963               get(i);
2964           final JMenuItem method = new JMenuItem(sh.getName());
2965           method.addActionListener(new ActionListener()
2966           {
2967             public void actionPerformed(ActionEvent e)
2968             {
2969               AlignmentView msa = gatherSequencesForAlignment();
2970               new jalview.ws.MsaWSClient(sh, title, msa,
2971                   false, true, viewport.getAlignment().getDataset(), af);
2972
2973             }
2974
2975           });
2976           msawsmenu.add(method);
2977           // Deal with services that we know accept partial alignments.
2978           if (sh.getName().indexOf("lustal") > -1)
2979           {
2980             // We know that ClustalWS can accept partial alignments for refinement.
2981             final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");
2982             methodR.addActionListener(new ActionListener()
2983             {
2984               public void actionPerformed(ActionEvent e)
2985               {
2986                 AlignmentView msa = gatherSequencesForAlignment();
2987                 new jalview.ws.MsaWSClient(sh, title, msa,
2988                     true, true, viewport.getAlignment().getDataset(), af);
2989
2990               }
2991
2992             });
2993             msawsmenu.add(methodR);
2994
2995           }
2996         }
2997         wsmenu.add(msawsmenu);
2998       }
2999       if (secstrpr != null)
3000       {
3001         // Add any secondary structure prediction services
3002         final JMenu secstrmenu = new JMenu("Secondary Structure Prediction");
3003         for (int i = 0, j = secstrpr.size(); i < j; i++)
3004         {
3005           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)
3006               secstrpr.get(i);
3007           final JMenuItem method = new JMenuItem(sh.getName());
3008           method.addActionListener(new ActionListener()
3009           {
3010             public void actionPerformed(ActionEvent e)
3011             {
3012               AlignmentView msa = gatherSeqOrMsaForSecStrPrediction();
3013               if (msa.getSequences().length == 1)
3014               {
3015                 // Single Sequence prediction
3016                 new jalview.ws.JPredClient(sh, title, false, msa, af, true);
3017               }
3018               else
3019               {
3020                 if (msa.getSequences().length > 1)
3021                 {
3022                   // Sequence profile based prediction
3023                   new jalview.ws.JPredClient(sh,
3024                       title, true, msa, af, true);
3025                 }
3026               }
3027             }
3028           });
3029           secstrmenu.add(method);
3030         }
3031         wsmenu.add(secstrmenu);
3032       }
3033       this.webService.removeAll();
3034       for (int i = 0, j = wsmenu.size(); i < j; i++)
3035       {
3036         webService.add( (JMenu) wsmenu.get(i));
3037       }
3038     }
3039     else
3040     {
3041       this.webService.removeAll();
3042       this.webService.add(this.webServiceNoServices);
3043     }
3044     // TODO: add in rediscovery function
3045     // TODO: reduce code redundancy.
3046     // TODO: group services by location as well as function.
3047   }
3048
3049  /* public void vamsasStore_actionPerformed(ActionEvent e)
3050   {
3051     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
3052         getProperty("LAST_DIRECTORY"));
3053
3054     chooser.setFileView(new JalviewFileView());
3055     chooser.setDialogTitle("Export to Vamsas file");
3056     chooser.setToolTipText("Export");
3057
3058     int value = chooser.showSaveDialog(this);
3059
3060     if (value == JalviewFileChooser.APPROVE_OPTION)
3061     {
3062       jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);
3063       //vs.store(chooser.getSelectedFile().getAbsolutePath()   );
3064       vs.storeJalview( chooser.getSelectedFile().getAbsolutePath(), this);
3065     }
3066   }*/
3067
3068
3069
3070
3071 public void showTranslation_actionPerformed(ActionEvent e)
3072 {
3073   SequenceI [] selection = viewport.getSelectionAsNewSequence();
3074   String [] seqstring = viewport.getViewAsString(true);
3075
3076   int s, sSize = selection.length;
3077   SequenceI [] newSeq = new SequenceI[sSize];
3078
3079   int res, resSize;
3080   StringBuffer protein;
3081   String seq;
3082   for(s=0; s<sSize; s++)
3083   {
3084     protein = new StringBuffer();
3085     seq = AlignSeq.extractGaps("-. ", seqstring[s]);
3086     resSize = seq.length();
3087     resSize -= resSize%3;
3088
3089     for(res = 0; res < resSize; res+=3)
3090     {
3091       String codon = seq.substring(res, res+3);
3092       codon = codon.replace('U', 'T');
3093       String aa = ResidueProperties.codonTranslate(codon);
3094       if(aa==null)
3095         protein.append(viewport.getGapCharacter());
3096       else if(aa.equals("STOP"))
3097         protein.append("X");
3098       else
3099         protein.append( aa );
3100     }
3101     newSeq[s] = new Sequence(selection[s].getName(),
3102                              protein.toString());
3103   }
3104
3105
3106   AlignmentI al = new Alignment(newSeq);
3107   al.setDataset(null);
3108
3109
3110   ////////////////////////////////
3111   // Copy annotations across
3112   jalview.datamodel.AlignmentAnnotation[] annotations
3113       = viewport.alignment.getAlignmentAnnotation();
3114   int a, aSize;
3115   if(annotations!=null)
3116   {
3117     for (int i = 0; i < annotations.length; i++)
3118     {
3119       if (annotations[i].label.equals("Quality") ||
3120           annotations[i].label.equals("Conservation") ||
3121           annotations[i].label.equals("Consensus"))
3122       {
3123         continue;
3124       }
3125
3126       aSize = viewport.alignment.getWidth() / 3;
3127       jalview.datamodel.Annotation[] anots =
3128           new jalview.datamodel.Annotation[aSize];
3129
3130       for (a = 0; a < viewport.alignment.getWidth(); a++)
3131       {
3132         if (annotations[i].annotations[a] == null
3133             || annotations[i].annotations[a] == null)
3134           continue;
3135
3136         anots[a / 3] = new Annotation(
3137             annotations[i].annotations[a].displayCharacter,
3138             annotations[i].annotations[a].description,
3139             annotations[i].annotations[a].secondaryStructure,
3140             annotations[i].annotations[a].value,
3141             annotations[i].annotations[a].colour);
3142       }
3143
3144       jalview.datamodel.AlignmentAnnotation aa
3145           = new jalview.datamodel.AlignmentAnnotation(annotations[i].label,
3146           annotations[i].description, anots);
3147       al.addAnnotation(aa);
3148     }
3149   }
3150
3151     AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
3152     Desktop.addInternalFrame(af, "Translation of "+this.getTitle(),
3153                              DEFAULT_WIDTH,
3154                              DEFAULT_HEIGHT);
3155
3156
3157
3158
3159 }
3160
3161 /**
3162  * DOCUMENT ME!
3163  *
3164  * @param String DOCUMENT ME!
3165  */
3166 public boolean parseFeaturesFile(String file, String type)
3167 {
3168     boolean featuresFile = false;
3169     try{
3170       featuresFile = new FeaturesFile(file, type).parse(viewport.alignment.getDataset(),
3171                                          alignPanel.seqPanel.seqCanvas.
3172                                          getFeatureRenderer().featureColours,
3173                                          false);
3174     }
3175     catch(Exception ex)
3176     {
3177       ex.printStackTrace();
3178     }
3179
3180     if(featuresFile)
3181     {
3182       viewport.showSequenceFeatures = true;
3183       showSeqFeatures.setSelected(true);
3184       alignPanel.repaint();
3185     }
3186
3187     return featuresFile;
3188 }
3189
3190 public void dragEnter(DropTargetDragEvent evt)
3191 {}
3192
3193 public void dragExit(DropTargetEvent evt)
3194 {}
3195
3196 public void dragOver(DropTargetDragEvent evt)
3197 {}
3198
3199 public void dropActionChanged(DropTargetDragEvent evt)
3200 {}
3201
3202 public void drop(DropTargetDropEvent evt)
3203 {
3204     Transferable t = evt.getTransferable();
3205     java.util.List files = null;
3206
3207     try
3208     {
3209       DataFlavor uriListFlavor = new DataFlavor("text/uri-list;class=java.lang.String");
3210       if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
3211       {
3212         //Works on Windows and MacOSX
3213         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3214         files = (java.util.List) t.getTransferData(DataFlavor.javaFileListFlavor);
3215       }
3216       else if (t.isDataFlavorSupported(uriListFlavor))
3217       {
3218         // This is used by Unix drag system
3219         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
3220         String data = (String) t.getTransferData(uriListFlavor);
3221         files = new java.util.ArrayList(1);
3222         for (java.util.StringTokenizer st = new java.util.StringTokenizer(
3223             data,
3224             "\r\n");
3225              st.hasMoreTokens(); )
3226         {
3227           String s = st.nextToken();
3228           if (s.startsWith("#"))
3229           {
3230             // the line is a comment (as per the RFC 2483)
3231             continue;
3232           }
3233
3234           java.net.URI uri = new java.net.URI(s);
3235           java.io.File file = new java.io.File(uri);
3236           files.add(file);
3237         }
3238       }
3239     }
3240     catch (Exception e)
3241     {
3242       e.printStackTrace();
3243     }
3244     if (files != null)
3245     {
3246       try
3247       {
3248
3249         for (int i = 0; i < files.size(); i++)
3250         {
3251           loadJalviewDataFile(files.get(i).toString());
3252         }
3253       }
3254       catch (Exception ex)
3255       {
3256         ex.printStackTrace();
3257       }
3258     }
3259 }
3260
3261   // This method will attempt to load a "dropped" file first by testing
3262   // whether its and Annotation file, then features file. If both are
3263   // false then the user may have dropped an alignment file onto this
3264   // AlignFrame
3265    public void loadJalviewDataFile(String file)
3266   {
3267     try{
3268       String protocol = "File";
3269
3270       if (file.indexOf("http:") > -1 || file.indexOf("file:") > -1)
3271       {
3272         protocol = "URL";
3273       }
3274
3275       boolean isAnnotation = new AnnotationFile().readAnnotationFile(viewport.
3276           alignment, file);
3277
3278       if (!isAnnotation)
3279       {
3280         boolean isGroupsFile = parseFeaturesFile(file,protocol);
3281         if (!isGroupsFile)
3282         {
3283           String format = new IdentifyFile().Identify(file, protocol);
3284
3285           if(format.equalsIgnoreCase("JnetFile"))
3286           {
3287             jalview.io.JPredFile predictions = new jalview.io.JPredFile(
3288                 file, protocol);
3289             new JnetAnnotationMaker().add_annotation(predictions,
3290                 viewport.getAlignment(),
3291                 0, false);
3292             alignPanel.adjustAnnotationHeight();
3293             alignPanel.repaint();
3294           }
3295           else
3296             new FileLoader().LoadFile(viewport, file, protocol, format);
3297         }
3298       }
3299       else
3300       {
3301         // (isAnnotation)
3302         alignPanel.adjustAnnotationHeight();
3303       }
3304
3305     }catch(Exception ex)
3306     {
3307       ex.printStackTrace();
3308     }
3309   }
3310
3311   public void tabSelectionChanged(int index)
3312   {
3313     if (index > -1)
3314     {
3315       alignPanel = (AlignmentPanel) alignPanels.elementAt(index);
3316       viewport = alignPanel.av;
3317       setMenusFromViewport(viewport);
3318     }
3319   }
3320
3321   public void tabbedPane_mousePressed(MouseEvent e)
3322   {
3323     if(SwingUtilities.isRightMouseButton(e))
3324     {
3325       String reply = JOptionPane.showInternalInputDialog(this,
3326           "Enter View Name",
3327           "Edit View Name",
3328           JOptionPane.QUESTION_MESSAGE);
3329
3330       if (reply != null)
3331       {
3332         viewport.viewName = reply;
3333         tabbedPane.setTitleAt( tabbedPane.getSelectedIndex() ,reply);
3334       }
3335     }
3336   }
3337
3338
3339   public AlignViewport getCurrentView()
3340   {
3341     return viewport;
3342   }
3343 }