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