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