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