fixed stacktrace potential for pairwise alignment action.
[jalview.git] / src / jalview / gui / AlignFrame.java
1 /********************
2  * 2004 Jalview Reengineered
3  * Barton Group
4  * Dundee University
5  *
6  * AM Waterhouse
7  *******************/
8
9
10
11
12 package jalview.gui;
13
14 import java.util.*;
15
16 import java.awt.*;
17 import java.awt.datatransfer.*;
18 import java.awt.event.*;
19 import java.awt.print.*;
20 import javax.swing.*;
21 import javax.swing.event.*;
22
23 import jalview.analysis.*;
24 import jalview.datamodel.*;
25 import jalview.io.*;
26 import jalview.jbgui.*;
27 import jalview.schemes.*;
28 import jalview.ws.*;
29 import java.beans.PropertyChangeEvent;
30
31 public class AlignFrame extends GAlignFrame
32 {
33   final AlignmentPanel alignPanel;
34   final AlignViewport viewport;
35   public static final int NEW_WINDOW_WIDTH = 700;
36   public static final int NEW_WINDOW_HEIGHT = 500;
37   public String currentFileFormat = "Jalview";
38
39   public AlignFrame(AlignmentI al)
40   {
41     viewport = new AlignViewport(al);
42
43     alignPanel = new AlignmentPanel(this, viewport);
44     alignPanel.annotationPanel.adjustPanelHeight();
45     alignPanel.annotationSpaceFillerHolder.setPreferredSize(alignPanel.annotationPanel.getPreferredSize());
46     alignPanel.annotationScroller.setPreferredSize(alignPanel.annotationPanel.getPreferredSize());
47     alignPanel.setAnnotationVisible( viewport.getShowAnnotation() );
48
49     getContentPane().add(alignPanel, java.awt.BorderLayout.CENTER);
50
51     addInternalFrameListener(new InternalFrameAdapter()
52    {
53      public void internalFrameActivated(InternalFrameEvent evt)
54      {
55           javax.swing.SwingUtilities.invokeLater(new Runnable()
56           {
57             public void run()
58             {      alignPanel.requestFocus();    }
59           });
60
61      }
62    });
63
64   }
65
66   public void saveAlignmentMenu_actionPerformed(ActionEvent e)
67   {
68     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty("LAST_DIRECTORY")
69         ,  new String[]{"fa, fasta, fastq", "aln",  "pfam", "msf", "pir","blc","jar"},
70           new String[]{"Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview"},
71           currentFileFormat);
72
73     chooser.setAcceptAllFileFilterUsed(false);
74     chooser.setFileView(new JalviewFileView());
75     chooser.setDialogTitle("Save Alignment to file");
76     chooser.setToolTipText("Save");
77     int value = chooser.showSaveDialog(this);
78     if(value == JalviewFileChooser.APPROVE_OPTION)
79     {
80       currentFileFormat  = chooser.getSelectedFormat();
81       jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat);
82
83       if (currentFileFormat.equals("Jalview"))
84       {
85         String shortName = title.replace('/', '_');
86         title = title.replace('\\', '_');
87         String choice = chooser.getSelectedFile().getPath();
88         Jalview2XML.SaveState(this, choice, shortName);
89         // USE Jalview2XML to save this file
90         return;
91       }
92
93       String choice =  chooser.getSelectedFile().getPath();
94       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
95       String output = FormatAdapter.formatSequences(currentFileFormat, viewport.getAlignment().getSequences());
96       try{
97         java.io.PrintWriter out = new java.io.PrintWriter( new java.io.FileWriter( choice )  );
98         out.println(output);
99         out.close();
100       }
101       catch(Exception ex){}
102     }
103
104   }
105
106   protected void outputText_actionPerformed(ActionEvent e)
107   {
108      CutAndPasteTransfer cap = new CutAndPasteTransfer();
109      Desktop.addInternalFrame(cap, "Alignment output - "+e.getActionCommand(), 600, 500);
110      cap.setText( FormatAdapter.formatSequences(e.getActionCommand(), viewport.getAlignment().getSequences()));
111   }
112
113   protected void htmlMenuItem_actionPerformed(ActionEvent e)
114   {
115     new HTMLOutput(viewport);
116   }
117
118   protected void createPNG_actionPerformed(ActionEvent e)
119   {
120     alignPanel.makePNG();
121   }
122
123   protected void epsFile_actionPerformed(ActionEvent e)
124   {
125     alignPanel.makeEPS();
126   }
127
128
129   public void printMenuItem_actionPerformed(ActionEvent e)
130   {
131     //Putting in a thread avoids Swing painting problems
132     PrintThread thread = new PrintThread();
133     thread.start();
134   }
135
136   class PrintThread extends Thread
137   {
138     public void run()
139     {
140       PrinterJob printJob = PrinterJob.getPrinterJob();
141       PageFormat pf = printJob.pageDialog(printJob.defaultPage());
142       printJob.setPrintable(alignPanel, pf);
143       if (printJob.printDialog())
144       {
145         try
146         {
147           printJob.print();
148         }
149         catch (Exception PrintException)
150         {
151           PrintException.printStackTrace();
152         }
153       }
154     }
155
156   }
157
158
159
160
161   public void closeMenuItem_actionPerformed(ActionEvent e)
162   {
163     try{
164       this.setClosed(true);
165     }catch(Exception ex){}
166   }
167
168   Stack historyList = new Stack();
169   Stack redoList = new Stack();
170   private int treeCount = 0;
171
172   void updateEditMenuBar()
173    {
174      if(historyList.size()>0)
175       {
176         undoMenuItem.setEnabled(true);
177         HistoryItem hi = (HistoryItem)historyList.peek();
178         undoMenuItem.setText("Undo "+hi.getDescription());
179       }
180      else
181      {
182        undoMenuItem.setEnabled(false);
183        undoMenuItem.setText("Undo");
184      }
185
186      if(redoList.size()>0)
187       {
188         redoMenuItem.setEnabled(true);
189         HistoryItem hi = (HistoryItem)redoList.peek();
190         redoMenuItem.setText("Redo "+hi.getDescription());
191       }
192      else
193      {
194        redoMenuItem.setEnabled(false);
195        redoMenuItem.setText("Redo");
196      }
197    }
198
199    public void addHistoryItem(HistoryItem hi)
200    {
201      historyList.push(hi);
202      updateEditMenuBar();
203    }
204
205    protected void undoMenuItem_actionPerformed(ActionEvent e)
206    {
207        HistoryItem hi = (HistoryItem)historyList.pop();
208        redoList.push(new HistoryItem(hi.getDescription(), viewport.alignment, HistoryItem.HIDE));
209        restoreHistoryItem(hi);
210    }
211
212
213    protected void redoMenuItem_actionPerformed(ActionEvent e)
214    {
215       HistoryItem hi = (HistoryItem)redoList.pop();
216       restoreHistoryItem(hi);
217       updateEditMenuBar();
218       viewport.updateConsensus();
219       alignPanel.repaint();
220       alignPanel.repaint();
221    }
222
223
224    // used by undo and redo
225    void restoreHistoryItem(HistoryItem hi)
226    {
227       if(hi.getType()== HistoryItem.SORT)
228       {
229            for(int i=0; i<hi.getSequences().size(); i++)
230              viewport.alignment.getSequences().setElementAt(hi.getSequences().elementAt(i), i);
231       }
232       else
233       {
234         for (int i = 0; i < hi.getSequences().size(); i++)
235         {
236           SequenceI restore = (SequenceI) hi.getSequences().elementAt(i);
237           if(restore.getLength()==0)
238           {
239             restore.setSequence(hi.getHidden().elementAt(i).toString());
240             viewport.alignment.getSequences().insertElementAt(
241                restore,
242                hi.getAlignIndex(i));
243           }
244           else
245             restore.setSequence(hi.getHidden().elementAt(i).toString());
246         }
247         if(hi.getType()==HistoryItem.PASTE)
248         {
249           for(int i=viewport.alignment.getHeight()-1;i>hi.getSequences().size()-1; i--)
250             viewport.alignment.deleteSequence(i);
251         }
252       }
253       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
254       updateEditMenuBar();
255
256       viewport.updateConsensus();
257       viewport.updateConservation();
258       alignPanel.repaint();
259   }
260
261   public void moveSelectedSequences(boolean up)
262   {
263     SequenceGroup sg = viewport.getSelectionGroup();
264     if (sg == null)
265       return;
266
267     if (up)
268     {
269       for (int i = 1; i < viewport.alignment.getHeight(); i++)
270       {
271         SequenceI seq = viewport.alignment.getSequenceAt(i);
272         if (!sg.sequences.contains(seq))
273           continue;
274
275         SequenceI temp = viewport.alignment.getSequenceAt(i - 1);
276         if (sg.sequences.contains(temp))
277           continue;
278
279         viewport.alignment.getSequences().setElementAt(temp, i);
280         viewport.alignment.getSequences().setElementAt(seq, i - 1);
281       }
282     }
283     else
284     {
285       for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)
286       {
287         SequenceI seq = viewport.alignment.getSequenceAt(i);
288         if (!sg.sequences.contains(seq))
289           continue;
290
291         SequenceI temp = viewport.alignment.getSequenceAt(i + 1);
292         if (sg.sequences.contains(temp))
293           continue;
294
295         viewport.alignment.getSequences().setElementAt(temp, i);
296         viewport.alignment.getSequences().setElementAt(seq, i + 1);
297       }
298     }
299
300     alignPanel.repaint();
301   }
302
303
304
305   protected void copy_actionPerformed(ActionEvent e)
306   {
307      if(viewport.getSelectionGroup()==null)
308        return;
309
310      SequenceGroup sg = viewport.getSelectionGroup();
311
312      Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
313      StringBuffer buffer= new StringBuffer();
314
315      Hashtable orderedSeqs = new Hashtable();
316      for(int i=0; i<sg.getSize(); i++)
317      {
318         SequenceI seq = sg.getSequenceAt(i);
319         int index = viewport.alignment.findIndex(seq);
320         orderedSeqs.put(index+"", seq);
321      }
322
323      int index=0;
324      for(int i=0; i<sg.getSize(); i++)
325      {
326        SequenceI seq = null;
327        while( seq == null )
328        {
329          if(orderedSeqs.containsKey(index+""))
330          {
331            seq = (SequenceI) orderedSeqs.get(index + "");
332            index++;
333            break;
334          }
335          else
336            index++;
337        }
338
339          buffer.append( seq.getName()+"\t"+seq.findPosition( sg.getStartRes() ) +"\t"
340                         +seq.findPosition( sg.getEndRes() )+ "\t"
341                         +sg.getSequenceAt(i).getSequence(sg.getStartRes(), sg.getEndRes()+1)+"\n");
342      }
343      c.setContents( new StringSelection( buffer.toString()) , null ) ;
344
345   }
346
347
348   protected void pasteNew_actionPerformed(ActionEvent e)
349   {
350     paste(true);
351   }
352
353   protected void pasteThis_actionPerformed(ActionEvent e)
354   {
355     addHistoryItem(new HistoryItem("Paste Sequences", viewport.alignment, HistoryItem.PASTE));
356     paste(false);
357   }
358
359   void paste(boolean newAlignment)
360   {
361     try{
362       Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
363       Transferable contents = c.getContents(this);
364       if (contents == null)
365         return;
366
367       String str = (String) contents.getTransferData(DataFlavor.stringFlavor);
368       StringTokenizer st = new StringTokenizer(str);
369       ArrayList seqs = new ArrayList();
370       while (st.hasMoreElements())
371       {
372         String name = st.nextToken();
373         int start = Integer.parseInt(st.nextToken());
374         int end = Integer.parseInt(st.nextToken());
375         Sequence sequence = new Sequence(name,st.nextToken(), start, end);
376
377         if(!newAlignment)
378           viewport.alignment.addSequence(sequence);
379         else
380           seqs.add(sequence);
381       }
382
383       if(newAlignment)
384       {
385         SequenceI[] newSeqs = new SequenceI[seqs.size()];
386         seqs.toArray(newSeqs);
387         AlignFrame af = new AlignFrame(new Alignment(newSeqs));
388         String newtitle = new String("Copied sequences");
389         if( title.startsWith("Copied sequences"))
390          newtitle = title;
391        else
392          newtitle = newtitle.concat("- from "+title);
393
394         Desktop.addInternalFrame(af, newtitle, NEW_WINDOW_WIDTH, NEW_WINDOW_HEIGHT);
395       }
396       else
397       {
398         viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
399         viewport.setEndSeq(viewport.alignment.getHeight());
400         viewport.alignment.getWidth();
401         viewport.updateConservation();
402         viewport.updateConsensus();
403         alignPanel.repaint();
404       }
405
406     }catch(Exception ex){}// could be anything being pasted in here
407
408   }
409
410
411   protected void cut_actionPerformed(ActionEvent e)
412   {
413     copy_actionPerformed(null);
414     delete_actionPerformed(null);
415   }
416
417   protected void delete_actionPerformed(ActionEvent e)
418   {
419     boolean seqsdeleted=false;
420
421     if (viewport.getSelectionGroup() == null)
422       return;
423
424     addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment, HistoryItem.HIDE));
425
426      SequenceGroup sg = viewport.getSelectionGroup();
427      for (int i=0;i < sg.sequences.size(); i++)
428      {
429        SequenceI seq = sg.getSequenceAt(i);
430        int index = viewport.getAlignment().findIndex(seq);
431        seq.deleteChars(sg.getStartRes(),sg.getEndRes()+1);
432
433        if(seq.getSequence().length()<1) {
434          seqsdeleted=true;
435          viewport.getAlignment().deleteSequence(seq);
436         } else {
437          viewport.getAlignment().getSequences().setElementAt(seq, index);
438        }
439      }
440
441      viewport.setSelectionGroup(null);
442      viewport.alignment.deleteGroup(sg);
443      if (seqsdeleted)
444        viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
445      viewport.resetSeqLimits( alignPanel.seqPanel.seqCanvas.getHeight());
446      if(viewport.getAlignment().getHeight()<1)
447      try
448      {
449        this.setClosed(true);
450      }catch(Exception ex){}
451    viewport.updateConservation();
452    viewport.updateConsensus();
453    alignPanel.repaint();
454  }
455
456
457   protected void deleteGroups_actionPerformed(ActionEvent e)
458   {
459     viewport.alignment.deleteAllGroups();
460     viewport.setSelectionGroup(null);
461     alignPanel.repaint();
462   }
463
464
465
466   public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
467   {
468     SequenceGroup sg = new SequenceGroup();
469     for (int i=0; i<viewport.getAlignment().getSequences().size(); i++)
470       sg.addSequence( viewport.getAlignment().getSequenceAt(i));
471     sg.setEndRes(viewport.alignment.getWidth());
472     viewport.setSelectionGroup(sg);
473     PaintRefresher.Refresh(null);
474   }
475
476   public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
477   {
478     viewport.setSelectionGroup(null);
479     viewport.getColumnSelection().clear();
480     viewport.setSelectionGroup(null);
481     PaintRefresher.Refresh(null);
482   }
483
484   public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
485   {
486     SequenceGroup sg = viewport.getSelectionGroup();
487     for (int i=0; i<viewport.getAlignment().getSequences().size(); i++)
488       sg.addOrRemove (viewport.getAlignment().getSequenceAt(i));
489
490     PaintRefresher.Refresh(null);
491   }
492
493   public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
494   {
495     ColumnSelection colSel = viewport.getColumnSelection();
496     if (colSel.size() > 0)
497     {
498       addHistoryItem(new HistoryItem("Remove Left",viewport.alignment,
499                                      HistoryItem.HIDE));
500       int min = colSel.getMin();
501       viewport.getAlignment().trimLeft(min);
502       colSel.compensateForEdit(0,min);
503
504       if(viewport.getSelectionGroup()!=null)
505         viewport.getSelectionGroup().adjustForRemoveLeft(min);
506
507       Vector groups = viewport.alignment.getGroups();
508       for(int i=0; i<groups.size(); i++)
509       {
510         SequenceGroup sg = (SequenceGroup) groups.get(i);
511         if(!sg.adjustForRemoveLeft(min))
512           viewport.alignment.deleteGroup(sg);
513       }
514
515       alignPanel.repaint();
516     }
517   }
518
519   public void remove2RightMenuItem_actionPerformed(ActionEvent e)
520   {
521     ColumnSelection colSel = viewport.getColumnSelection();
522     if (colSel.size() > 0)
523     {
524       addHistoryItem(new HistoryItem("Remove Right",viewport.alignment,
525                                      HistoryItem.HIDE));
526
527       int max = colSel.getMax();
528       viewport.getAlignment().trimRight(max);
529       if(viewport.getSelectionGroup()!=null)
530         viewport.getSelectionGroup().adjustForRemoveRight(max);
531
532       Vector groups = viewport.alignment.getGroups();
533       for(int i=0; i<groups.size(); i++)
534       {
535         SequenceGroup sg = (SequenceGroup) groups.get(i);
536         if(!sg.adjustForRemoveRight(max))
537           viewport.alignment.deleteGroup(sg);
538       }
539
540
541
542       alignPanel.repaint();
543     }
544
545   }
546
547   public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
548   {
549     addHistoryItem(new HistoryItem("Remove Gapped Columns",
550                                    viewport.alignment,
551                                    HistoryItem.HIDE));
552
553     viewport.getAlignment().removeGaps();
554     viewport.updateConservation();
555     viewport.updateConsensus();
556     alignPanel.repaint();
557   }
558
559   public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
560   {
561     addHistoryItem(new HistoryItem("Remove Gaps",
562                                    viewport.alignment,
563                                    HistoryItem.HIDE));
564     SequenceI current;
565     int jSize;
566     for (int i=0; i < viewport.getAlignment().getSequences().size();i++)
567     {
568       current = viewport.getAlignment().getSequenceAt(i);
569       jSize = current.getLength();
570       for (int j=0; j < jSize; j++)
571         if(jalview.util.Comparison.isGap(current.getCharAt(j)))
572         {
573           current.deleteCharAt(j);
574           j--;
575           jSize--;
576         }
577     }
578     viewport.updateConservation();
579     viewport.updateConsensus();
580     alignPanel.repaint();
581   }
582
583
584   public void padGapsMenuitem_actionPerformed(ActionEvent e)
585     {
586       addHistoryItem(new HistoryItem("Pad Gaps",
587                                      viewport.alignment,
588                                      HistoryItem.HIDE));
589       SequenceI current;
590       int Width = viewport.getAlignment().getWidth()-1;
591       for (int i=0; i < viewport.getAlignment().getSequences().size();i++)
592       {
593         current = viewport.getAlignment().getSequenceAt(i);
594
595         if (current.getLength()<Width)
596           current.insertCharAt(Width, viewport.getGapCharacter());
597       }
598       viewport.updateConservation();
599       viewport.updateConsensus();
600       alignPanel.repaint();
601   }
602
603
604   public void findMenuItem_actionPerformed(ActionEvent e)
605   {
606     JInternalFrame frame = new JInternalFrame();
607     Finder finder = new Finder(viewport, alignPanel, frame);
608     frame.setContentPane(finder);
609     Desktop.addInternalFrame(frame, "Find", 340,110);
610     frame.setLayer(JLayeredPane.PALETTE_LAYER);
611
612   }
613
614
615   public void font_actionPerformed(ActionEvent e)
616   {
617     FontChooser fc = new FontChooser( alignPanel );
618   }
619
620   protected void fullSeqId_actionPerformed(ActionEvent e)
621   {
622     viewport.setShowFullId( fullSeqId.isSelected() );
623
624     alignPanel.idPanel.idCanvas.setPreferredSize( alignPanel.calculateIdWidth() );
625     alignPanel.repaint();
626   }
627
628   protected void colourTextMenuItem_actionPerformed(ActionEvent e)
629   {
630       viewport.setColourText( colourTextMenuItem.isSelected() );
631       alignPanel.repaint();
632   }
633
634   protected void wrapMenuItem_actionPerformed(ActionEvent e)
635   {
636     viewport.setWrapAlignment( wrapMenuItem.isSelected() );
637     alignPanel.setWrapAlignment( wrapMenuItem.isSelected() );
638     scaleAbove.setVisible( wrapMenuItem.isSelected() );
639     scaleLeft.setVisible( wrapMenuItem.isSelected() );
640     scaleRight.setVisible( wrapMenuItem.isSelected() );
641     alignPanel.repaint();
642   }
643
644   protected void scaleAbove_actionPerformed(ActionEvent e)
645   {
646     viewport.setScaleAboveWrapped(scaleAbove.isSelected());
647     alignPanel.repaint();
648   }
649
650   protected void scaleLeft_actionPerformed(ActionEvent e)
651   {
652     viewport.setScaleLeftWrapped(scaleLeft.isSelected());
653     alignPanel.repaint();
654   }
655
656   protected void scaleRight_actionPerformed(ActionEvent e)
657   {
658     viewport.setScaleRightWrapped(scaleRight.isSelected());
659     alignPanel.repaint();
660   }
661
662
663
664   public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
665   {
666     viewport.setShowBoxes( viewBoxesMenuItem.isSelected() );
667     alignPanel.repaint();
668   }
669
670   public void viewTextMenuItem_actionPerformed(ActionEvent e)
671   {
672     viewport.setShowText( viewTextMenuItem.isSelected() );
673     alignPanel.repaint();
674   }
675
676
677   protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
678   {
679     viewport.setRenderGaps(renderGapsMenuItem.isSelected());
680     alignPanel.repaint();
681   }
682
683   public void sequenceFeatures_actionPerformed(ActionEvent evt)
684   {
685     viewport.showSequenceFeatures(sequenceFeatures.isSelected());
686     if(viewport.showSequenceFeatures && !((Alignment)viewport.alignment).featuresAdded)
687     {
688          SequenceFeatureFetcher sft = new SequenceFeatureFetcher(viewport.alignment, alignPanel);
689          ((Alignment)viewport.alignment).featuresAdded = true;
690     }
691     alignPanel.repaint();
692   }
693
694   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
695   {
696     if(annotationPanelMenuItem.isSelected() && viewport.getWrapAlignment())
697     {
698       annotationPanelMenuItem.setSelected(false);
699       return;
700     }
701     viewport.setShowAnnotation( annotationPanelMenuItem.isSelected() );
702     alignPanel.setAnnotationVisible( annotationPanelMenuItem.isSelected() );
703   }
704
705   public void overviewMenuItem_actionPerformed(ActionEvent e)
706   {
707     if (alignPanel.overviewPanel != null)
708       return;
709
710     JInternalFrame frame = new JInternalFrame();
711     OverviewPanel overview = new OverviewPanel(alignPanel);
712      frame.setContentPane(overview);
713     Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),
714                              frame.getWidth(), frame.getHeight());
715     frame.pack();
716     frame.setLayer(JLayeredPane.PALETTE_LAYER);
717     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
718     { public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt)
719       {
720             alignPanel.setOverviewPanel(null);
721       };
722     });
723
724     alignPanel.setOverviewPanel( overview );
725
726
727   }
728
729   protected void noColourmenuItem_actionPerformed(ActionEvent e)
730   {
731     changeColour( null );
732   }
733
734
735   public void clustalColour_actionPerformed(ActionEvent e)
736   {
737     changeColour(new ClustalxColourScheme(viewport.alignment.getSequences(), viewport.alignment.getWidth()));
738   }
739
740   public void zappoColour_actionPerformed(ActionEvent e)
741   {
742     changeColour(new ZappoColourScheme());
743   }
744
745   public void taylorColour_actionPerformed(ActionEvent e)
746   {
747     changeColour(new TaylorColourScheme());
748   }
749
750
751   public void hydrophobicityColour_actionPerformed(ActionEvent e)
752   {
753     changeColour( new HydrophobicColourScheme() );
754   }
755
756   public void helixColour_actionPerformed(ActionEvent e)
757   {
758     changeColour(new HelixColourScheme() );
759   }
760
761
762   public void strandColour_actionPerformed(ActionEvent e)
763   {
764     changeColour(new StrandColourScheme());
765   }
766
767
768   public void turnColour_actionPerformed(ActionEvent e)
769   {
770     changeColour(new TurnColourScheme());
771   }
772
773
774   public void buriedColour_actionPerformed(ActionEvent e)
775   {
776     changeColour(new BuriedColourScheme() );
777   }
778
779   public void nucleotideColour_actionPerformed(ActionEvent e)
780   {
781     changeColour(new NucleotideColourScheme());
782   }
783
784
785   protected void applyToAllGroups_actionPerformed(ActionEvent e)
786   {
787     viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
788   }
789
790
791
792   void changeColour(ColourSchemeI cs)
793   {
794     int threshold = 0;
795
796     if ( viewport.getAbovePIDThreshold() )
797     {
798       threshold = SliderPanel.setPIDSliderSource(alignPanel, cs, "Background");
799
800       if (cs instanceof ResidueColourScheme)
801         ( (ResidueColourScheme) cs).setThreshold(threshold);
802       else if (cs instanceof ScoreColourScheme)
803         ( (ScoreColourScheme) cs).setThreshold(threshold);
804
805       viewport.setGlobalColourScheme(cs);
806     }
807     else if (cs instanceof ResidueColourScheme)
808       ( (ResidueColourScheme) cs).setThreshold(0);
809     else if (cs instanceof ScoreColourScheme)
810       ( (ScoreColourScheme) cs).setThreshold(0);
811
812
813
814     if (viewport.getConservationSelected())
815     {
816       ConservationColourScheme ccs = null;
817
818       Alignment al = (Alignment) viewport.alignment;
819       Conservation c = new Conservation("All",
820                                         ResidueProperties.propHash, 3,
821                                         al.getSequences(), 0,
822                                         al.getWidth() - 1);
823
824       c.calculate();
825       c.verdict(false, viewport.ConsPercGaps);
826
827       ccs = new ConservationColourScheme(c, cs);
828
829       // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
830       ccs.setConsensus( viewport.vconsensus );
831       viewport.setGlobalColourScheme(ccs);
832
833       ccs.inc = SliderPanel.setConservationSlider(alignPanel, ccs, "Background");
834
835     }
836     else
837     {
838         // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
839         if (cs != null)
840           cs.setConsensus(viewport.vconsensus);
841         viewport.setGlobalColourScheme(cs);
842     }
843
844
845     if(viewport.getColourAppliesToAllGroups())
846     {
847       Vector groups = viewport.alignment.getGroups();
848       for(int i=0; i<groups.size(); i++)
849       {
850         SequenceGroup sg = (SequenceGroup)groups.elementAt(i);
851
852         if(cs==null)
853           sg.cs = null;
854         else if (cs instanceof ClustalxColourScheme)
855           sg.cs = new ClustalxColourScheme(sg.sequences, sg.getWidth());
856         else if (cs instanceof UserColourScheme)
857           sg.cs = new UserColourScheme( ((UserColourScheme)cs).getColours());
858         else
859           try{
860             sg.cs = (ColourSchemeI) cs.getClass().newInstance();
861           }catch(Exception ex){}
862
863         if(viewport.getAbovePIDThreshold())
864         {
865           if (sg.cs instanceof ResidueColourScheme)
866             ( (ResidueColourScheme) sg.cs).setThreshold(threshold);
867           else if (sg.cs instanceof ScoreColourScheme)
868             ( (ScoreColourScheme) sg.cs).setThreshold(threshold);
869
870            sg.cs.setConsensus( AAFrequency.calculate(sg.sequences, 0, sg.getWidth()) );
871         }
872
873         if( viewport.getConservationSelected() )
874         {
875           Conservation c = new Conservation("Group",
876                                             ResidueProperties.propHash, 3,
877                                             sg.sequences, 0, viewport.alignment.getWidth()-1);
878           c.calculate();
879           c.verdict(false, viewport.ConsPercGaps);
880           ConservationColourScheme ccs = new ConservationColourScheme(c, sg.cs);
881
882           // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
883           ccs.setConsensus( AAFrequency.calculate(sg.sequences, 0, sg.getWidth()));
884           sg.cs = ccs;
885         }
886         else if(cs!=null)
887         {
888           // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
889           sg.cs.setConsensus(AAFrequency.calculate(sg.sequences, 0, sg.getWidth()));
890         }
891
892       }
893     }
894
895     if(alignPanel.getOverviewPanel()!=null)
896       alignPanel.getOverviewPanel().updateOverviewImage();
897     alignPanel.repaint();
898   }
899
900   protected void modifyPID_actionPerformed(ActionEvent e)
901   {
902       if(viewport.getAbovePIDThreshold())
903       {
904         SliderPanel.setPIDSliderSource(alignPanel, viewport.getGlobalColourScheme(),
905                                    "Background");
906         SliderPanel.showPIDSlider();
907       }
908   }
909
910   protected void modifyConservation_actionPerformed(ActionEvent e)
911   {
912     if(viewport.getConservationSelected())
913     {
914       SliderPanel.setConservationSlider(alignPanel, viewport.globalColourScheme,
915                                         "Background");
916       SliderPanel.showConservationSlider();
917     }
918   }
919
920
921   protected  void conservationMenuItem_actionPerformed(ActionEvent e)
922   {
923     viewport.setConservationSelected(conservationMenuItem.isSelected());
924
925     viewport.setAbovePIDThreshold(false);
926     abovePIDThreshold.setSelected(false);
927
928    ColourSchemeI cs = viewport.getGlobalColourScheme();
929    if(cs instanceof ConservationColourScheme )
930      changeColour( ((ConservationColourScheme)cs).cs );
931     else
932       changeColour( cs );
933
934     modifyConservation_actionPerformed(null);
935   }
936
937   public void abovePIDThreshold_actionPerformed(ActionEvent e)
938   {
939     viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());
940
941     conservationMenuItem.setSelected(false);
942     viewport.setConservationSelected(false);
943
944     ColourSchemeI cs = viewport.getGlobalColourScheme();
945
946     if(cs instanceof ConservationColourScheme )
947         changeColour( ((ConservationColourScheme)cs).cs );
948     else
949         changeColour( cs );
950
951     modifyPID_actionPerformed(null);
952   }
953
954
955
956   public void userDefinedColour_actionPerformed(ActionEvent e)
957   {
958     new UserDefinedColours( alignPanel, null);
959   }
960
961   public void PIDColour_actionPerformed(ActionEvent e)
962   {
963     changeColour( new PIDColourScheme() );
964   }
965
966
967   public void BLOSUM62Colour_actionPerformed(ActionEvent e)
968   {
969     changeColour(new Blosum62ColourScheme() );
970   }
971
972
973
974   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
975   {
976     addHistoryItem(new HistoryItem("Pairwise Sort", viewport.alignment, HistoryItem.SORT));
977     AlignmentSorter.sortByPID(viewport.getAlignment(), viewport.getAlignment().getSequenceAt(0));
978     alignPanel.repaint();
979   }
980
981   public void sortIDMenuItem_actionPerformed(ActionEvent e)
982   {
983     addHistoryItem(new HistoryItem("ID Sort", viewport.alignment, HistoryItem.SORT));
984     AlignmentSorter.sortByID( viewport.getAlignment() );
985     alignPanel.repaint();
986   }
987
988   public void sortGroupMenuItem_actionPerformed(ActionEvent e)
989   {
990     addHistoryItem(new HistoryItem("Group Sort", viewport.alignment, HistoryItem.SORT));
991     AlignmentSorter.sortByGroup(viewport.getAlignment());
992     AlignmentSorter.sortGroups(viewport.getAlignment());
993     alignPanel.repaint();
994   }
995
996   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
997   {
998     RedundancyPanel sp = new RedundancyPanel(alignPanel,this);
999     JInternalFrame frame = new JInternalFrame();
1000     frame.setContentPane(sp);
1001     Desktop.addInternalFrame(frame, "Redundancy threshold selection", 400, 100, false);
1002
1003   }
1004
1005   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
1006   {
1007     if((viewport.getSelectionGroup()==null) ||
1008        viewport.getSelectionGroup().getSize()<2)
1009       JOptionPane.showInternalMessageDialog(this, "You must select at least 2 sequences.", "Invalid Selection", JOptionPane.WARNING_MESSAGE);
1010     else
1011     {
1012       JInternalFrame frame = new JInternalFrame();
1013       frame.setContentPane(new PairwiseAlignPanel(viewport));
1014       Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);
1015     }
1016   }
1017
1018   public void PCAMenuItem_actionPerformed(ActionEvent e)
1019   {
1020
1021     if( (viewport.getSelectionGroup()!=null && viewport.getSelectionGroup().getSize()<4 && viewport.getSelectionGroup().getSize()>0)
1022        || viewport.getAlignment().getHeight()<4)
1023     {
1024       JOptionPane.showInternalMessageDialog(this, "Principal component analysis must take\n"
1025                                     +"at least 4 input sequences.",
1026                                     "Sequence selection insufficient",
1027                                     JOptionPane.WARNING_MESSAGE);
1028       return;
1029     }
1030
1031     try{
1032       PCAPanel pcaPanel = new PCAPanel(viewport, null);
1033       JInternalFrame frame = new JInternalFrame();
1034       frame.setContentPane(pcaPanel);
1035       Desktop.addInternalFrame(frame, "Principal component analysis", 400, 400);
1036    }catch(java.lang.OutOfMemoryError ex)
1037    {
1038      JOptionPane.showInternalMessageDialog(this, "Too many sequences selected\nfor Principal Component Analysis!!",
1039                                    "Out of memory", JOptionPane.WARNING_MESSAGE);
1040    }
1041
1042
1043   }
1044
1045   public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
1046   {
1047     NewTreePanel("AV", "PID", "Average distance tree using PID");
1048   }
1049
1050   public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
1051   {
1052     NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
1053   }
1054
1055
1056   protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
1057   {
1058     NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
1059   }
1060
1061   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
1062   {
1063     NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
1064   }
1065
1066   void NewTreePanel(String type, String pwType, String title)
1067   {
1068     //are the sequences aligned?
1069     if(!viewport.alignment.isAligned())
1070     {
1071       JOptionPane.showMessageDialog(Desktop.desktop, "The sequences must be aligned before creating a tree.\n"
1072                                    +"Try using the Pad function in the edit menu,\n"
1073                                   +"or one of the multiple sequence alignment web services.",
1074                                     "Sequences not aligned", JOptionPane.WARNING_MESSAGE);
1075       return;
1076     }
1077
1078     final TreePanel tp;
1079     if (viewport.getSelectionGroup() != null &&
1080         viewport.getSelectionGroup().getSize() > 3)
1081     {
1082       tp = new TreePanel(viewport, viewport.getSelectionGroup().sequences, type,
1083                          pwType,
1084                          0, viewport.alignment.getWidth());
1085     }
1086     else
1087     {
1088       tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),
1089                          type, pwType, 0, viewport.alignment.getWidth());
1090     }
1091
1092    addTreeMenuItem(tp, title);
1093
1094    Desktop.addInternalFrame(tp, title, 600, 500);
1095   }
1096
1097   public void addSortByOrderMenuItem(String title, final AlignmentOrder order) {
1098     final JMenuItem item = new JMenuItem("by "+title);
1099     sort.add(item);
1100     item.addActionListener(new java.awt.event.ActionListener()
1101     {
1102       public void actionPerformed(ActionEvent e)
1103       {
1104         addHistoryItem(new HistoryItem("Sort", viewport.alignment,
1105                                        HistoryItem.SORT));
1106         // TODO: JBPNote - have to map order entries to curent SequenceI pointers
1107         AlignmentSorter.sortBy(viewport.getAlignment(), order);
1108         alignPanel.repaint();
1109       }
1110     });
1111   }
1112
1113   void addTreeMenuItem(final TreePanel treePanel, String title)
1114   {
1115     final JMenuItem item = new JMenuItem(title);
1116
1117     treeCount++;
1118
1119     if (treeCount==1)
1120       sort.add(sortByTreeMenu);
1121
1122     sortByTreeMenu.add(item);
1123     item.addActionListener(new java.awt.event.ActionListener()
1124     {
1125       public void actionPerformed(ActionEvent e)
1126       {
1127         addHistoryItem(new HistoryItem("Tree Sort", viewport.alignment,
1128                                        HistoryItem.SORT));
1129         AlignmentSorter.sortByTree(viewport.getAlignment(), treePanel.getTree());
1130         alignPanel.repaint();
1131       }
1132     });
1133
1134     treePanel.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
1135     {
1136       public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt)
1137       {
1138         treeCount--;
1139         sortByTreeMenu.remove(item);
1140         if (treeCount==0)
1141           sort.remove(sortByTreeMenu);
1142       };
1143     });
1144     viewport.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
1145       public void propertyChange(PropertyChangeEvent evt)
1146       {
1147         if (evt.getPropertyName().equals("alignment")) {
1148           treePanel.getTree().UpdatePlaceHolders( (Vector) evt.getNewValue());
1149           treePanel.repaint();
1150         }
1151       }
1152
1153     }
1154     );
1155   }
1156
1157
1158   public void clustalAlignMenuItem_actionPerformed(ActionEvent e)
1159   {
1160       // TODO:resolve which menu item was actually selected
1161       // Now, check we have enough sequences
1162         SequenceI[] msa=null;
1163         if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>1)
1164         {
1165           // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
1166           SequenceGroup seqs = viewport.getSelectionGroup();
1167           int sz;
1168           msa = new SequenceI[sz=seqs.getSize()];
1169           for (int i = 0; i < sz; i++)
1170           {
1171             msa[i] = (SequenceI) seqs.getSequenceAt(i);
1172           }
1173
1174           }
1175         else
1176         {
1177           Vector seqs = viewport.getAlignment().getSequences();
1178
1179           if (seqs.size() > 1) {
1180             msa = new SequenceI[seqs.size()];
1181             for (int i = 0; i < seqs.size(); i++)
1182             {
1183               msa[i] = (SequenceI) seqs.elementAt(i);
1184             }
1185
1186           }
1187
1188         }
1189         if (msa!=null) {
1190           jalview.ws.MsaWSClient ct = new jalview.ws.MsaWSClient("ClustalWS", title, msa, true, true);
1191         }
1192   }
1193
1194   protected void jpred_actionPerformed(ActionEvent e)
1195 {
1196     SequenceI seq=null;
1197     SequenceI[] msa=null;
1198
1199     if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>0)
1200     {
1201       // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
1202       SequenceGroup seqs = viewport.getSelectionGroup();
1203       if (seqs.getSize() == 1 || !viewport.alignment.isAligned())
1204       {
1205         seq = (SequenceI)seqs.getSequenceAt(0);
1206       }
1207       else
1208       {
1209         int sz;
1210         msa = new SequenceI[sz=seqs.getSize()];
1211         for (int i = 0; i < sz; i++)
1212         {
1213           msa[i] = (SequenceI) seqs.getSequenceAt(i);
1214         }
1215       }
1216     }
1217     else
1218     {
1219       Vector seqs = viewport.getAlignment().getSequences();
1220
1221       if (seqs.size() == 1 || !viewport.alignment.isAligned())
1222       {
1223         seq = (SequenceI) seqs.elementAt(0);
1224       }
1225       else
1226       {
1227         msa = new SequenceI[seqs.size()];
1228         for (int i = 0; i < seqs.size(); i++)
1229         {
1230           msa[i] = (SequenceI) seqs.elementAt(i);
1231         }
1232       }
1233     }
1234     if (msa!=null) {
1235       JPredClient ct = new JPredClient(title, msa);
1236     } else
1237     if (seq!=null) {
1238       JPredClient ct = new JPredClient(title, seq);
1239     } else {
1240       System.err.print("JALVIEW ERROR! - Unexpected JPred selection state!\n");
1241     }
1242   }
1243   protected void msaAlignMenuItem_actionPerformed(ActionEvent e)
1244   {
1245     // TODO:resolve which menu item was actually selected
1246     // Now, check we have enough sequences
1247     SequenceI[] msa=null;
1248     if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>1)
1249       {
1250         // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
1251         SequenceGroup seqs = viewport.getSelectionGroup();
1252         int sz;
1253         msa = new SequenceI[sz=seqs.getSize()];
1254         for (int i = 0; i < sz; i++)
1255         {
1256           msa[i] = (SequenceI) seqs.getSequenceAt(i);
1257         }
1258
1259
1260       }
1261       else
1262       {
1263         Vector seqs = viewport.getAlignment().getSequences();
1264
1265         if (seqs.size() > 1) {
1266           msa = new SequenceI[seqs.size()];
1267           for (int i = 0; i < seqs.size(); i++)
1268           {
1269             msa[i] = (SequenceI) seqs.elementAt(i);
1270           }
1271
1272         }
1273
1274       }
1275       if (msa!=null) {
1276         MsaWSClient ct = new jalview.ws.MsaWSClient("MuscleWS",title, msa, true, true);
1277       }
1278   }
1279     protected void LoadtreeMenuItem_actionPerformed(ActionEvent e) {
1280     // Pick the tree file
1281     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1282         getProperty("LAST_DIRECTORY"));
1283     chooser.setFileView(new JalviewFileView());
1284     chooser.setDialogTitle("Select a newick-like tree file");
1285     chooser.setToolTipText("Load a tree file");
1286     int value = chooser.showOpenDialog(null);
1287     if (value == JalviewFileChooser.APPROVE_OPTION)
1288     {
1289       String choice = chooser.getSelectedFile().getPath();
1290       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
1291       try
1292       {
1293         jalview.io.NewickFile fin = new jalview.io.NewickFile(choice, "File");
1294         ShowNewickTree(fin, choice);
1295       }
1296       catch (Exception ex)
1297       {
1298         JOptionPane.showMessageDialog(Desktop.desktop,
1299                                       "Problem reading tree file",
1300                                       ex.getMessage(),
1301                                       JOptionPane.WARNING_MESSAGE);
1302         ex.printStackTrace();
1303       }
1304     }
1305   }
1306
1307   public void ShowNewickTree(NewickFile nf, String title)
1308   {
1309     try{
1310       nf.parse();
1311       if (nf.getTree() != null)
1312       {
1313         TreePanel tp = new TreePanel(viewport,
1314                                      viewport.getAlignment().getSequences(),
1315                                      nf, "FromFile", title);
1316         Desktop.addInternalFrame(tp, title, 600, 500);
1317         addTreeMenuItem(tp, title);
1318         viewport.setCurrentTree(tp.getTree());
1319       }
1320      }catch(Exception ex){ex.printStackTrace();}
1321   }
1322
1323 }